1

I have the following array in Java:

int arr[] = {4,5,6};

I want to convert it into a java.util.Map<K,V> instance that has the index of the array as keys and the value at index as values for the Map. Like so,

0 = 4
1 = 5
2 = 6

I have tried the following:

IntStream.range(0, arr.length)
                 .collect(Collectors.toMap(k -> k, k -> arr[k]));

But this results in compilation errors like:

Type mismatch: cannot convert from Collector<Object,capture#1-of ?,Map<Object,Object>> to Supplier<R>

and

The method collect(Supplier<R>, ObjIntConsumer<R>, BiConsumer<R,R>) in the type IntStream is not applicable for the arguments (Collector<Object,?,Map<Object,Object>>)

What am I doing wrong here ?

I am just going over all the indices and then mapping them to keys and values where am I going wrong ?

ng.newbie
  • 2,807
  • 3
  • 23
  • 57
  • 4
    Does this answer your question? [Java 8 int array to map](https://stackoverflow.com/questions/56406621/java-8-int-array-to-map) – Harmandeep Singh Kalsi Jul 08 '20 at 17:27
  • 2
    `IntStream` has only one `collect` method: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/IntStream.html#collect(java.util.function.Supplier,java.util.function.ObjIntConsumer,java.util.function.BiConsumer). Try to map it to a `Stream` like this: `IntStream.range(0, arr.length).mapToObj(Integer::valueOf).collect(Collectors.toMap(k -> k, k -> Integer.valueOf(arr[k.intValue()])));`. – dan1st Jul 08 '20 at 17:28
  • Try to use a Stream of Integer by using IntStream#boxed instead. – Jason Jul 08 '20 at 17:34

4 Answers4

3

Try:

int arr[] = {4,5,6};
Map<Integer, Integer> resultMap = IntStream.range(0, arr.length).boxed()
                    .collect(Collectors.toMap(Function.identity(), k -> arr[k]));
resultMap.entrySet().forEach(entry -> System.out.println(entry.getKey() + " = " + entry.getValue()));

Output:

0 = 4
1 = 5
2 = 6
Nitin Bisht
  • 5,053
  • 4
  • 14
  • 26
2

You are using IntStream which is unboxed. You need to use .boxed().

If your array is ordered, yo can do:

int arr[] = {4,5,6};

Map<Integer, Integer> map = Arrays.stream(arr).boxed()
    .collect(Collectors.toMap(i -> Arrays.binarySearch(arr, i), Function.identity()));

map.entrySet().forEach(entry -> System.out.println(entry.getKey() + " = " + entry.getValue()));

If it's not ordered you can do:

Map<Integer, Integer> map = IntStream.range(0, arr.length).boxed()
        .collect(Collectors.toMap(Function.identity(), i -> arr[i]));
Oboe
  • 2,643
  • 2
  • 9
  • 17
  • What is `Function.identity()` ?? – ng.newbie Jul 08 '20 at 18:08
  • It is similar to i -> i (but not the same). From javadoc: "Returns a function that always returns its input argument.". If you want to get more info, try this answer: https://stackoverflow.com/questions/28032827/java-8-lambdas-function-identity-or-t-t – Oboe Jul 08 '20 at 18:45
1

You have to box the IntStream and use groupingBy value to get the wanted count.

Try this:

Map<Integer, Long> map = Arrays
        .stream(arr)
        .boxed()
        .collect(Collectors.groupingBy(e -> e, Collectors.counting()));

AztecCodes
  • 1,130
  • 7
  • 23
1

There are multiple solutions.

1. For-each loop

Map<Integer, Integer> map = new HashMap<>();
for (int i=0; i<arr.length; i++) {
    map.put(i, arr[i]);
}

In my opinion, this is the most clear in terms of readability.


2. IntStream with a range of the array length

Map<Integer, Integer> map = IntStream.range(0, arr.length)
    .boxed()
    .collect(Collectors.toMap(Function.identity(), i -> arr[i]));

This seems like your original attempt. You need either to box with boxed() to Stream<Integer> in order to use collect with a single Collector.


3. Stream::iterate and Stream::limit

Map<Integer, Integer> map = Stream.iterate(0, i -> i+1)
    .limit(arr.length)
    .collect(Collectors.toMap(Function.identity(), i -> arr[i]));

It's a simple endless generation of an increasing sequence by one limited by the length of the array.

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183