I was trying to something pretty simple, but it fails on compilation, and I can't understand who
I have a list of headers, I need to convert it to
Map<Index, String>
meaning the key (index) and the value is the header name
I know how to make it with for each, but I want to have it in Collectors.to
map
any help would be appreciated
final String[] headerDisplayName = getHeaderDisplayName(harmonizationComponentDataFixRequest);
IntStream.of(0, headerDisplayName.length).collect(Collectors.toMap(Function.identity(), index-> headerDisplayName[index]));
2 Answers 2
You can use range
method in combination with boxed
method of IntStream
.
(When you use the of
method like in your example, only 0 and the size of the array are in this stream. In addition this would lead to an ArrayIndexOutOfBoundsException
)
A possible solution would look like this (first parameter of the range
method is included, the second parameter is excluded)
Map<Integer, String> map = IntStream.range(0, headerDisplayName.length)
.boxed()
.collect(Collectors.toMap(
Function.identity(),
i -> headerDisplayName[i])
);
1 Comment
boxed()
solved this, check my answer for this question.Adding to the @csalmhof's answer, I think it's to explain here why using boxed
is working.
If you don't use boxed()
method and simply write the following:
Map<Integer, String> map = IntStream.range(0, headerDisplayName.length)
.collect(Collectors.toMap(
Function.identity(),
index -> headerDisplayName[index])
);
Java will have to take index
as of type Object
and there's no implicit conversion that can happen and so you'll get error.
But if you put boxed()
like in the following code, you won't get error:
Map<Integer, String> map = IntStream.range(0, headerDisplayName.length)
.boxed()
.collect(Collectors.toMap(
Function.identity(),
index -> headerDisplayName[index])
);
you're not getting error here because java interprets index
as an Integer
and there's implicit casting happening from Integer
to int
.
A good IDE can help you with this type of explanation. In IntelliJ if you press ctrl
+ space
after keeping your cursor on index
(with Eclipse key-map enabled) you will get the following without boxed()
.
And this is what you get when you've boxed()
placed.
enter image description here
I hope this clarifies why using boxed() is saving you from compilation error. Also, you can use this thing in future to find actual type of parameter in lambda which can be helpful in case cases (one of the case is the one that OP pointed out)
2 Comments
IntStream#collect(Collector)
method. There is, however, a Stream#collect(Collector)
method and that's why calling IntStream#boxed()
works, because it returns a Stream<Integer>
. The IDE error shown in this answer is "confused", probably by the fact that the IntStream#collect(Supplier,ObjIntConsumer,BiConsumer)
method exists. So the compiler sees there is indeed a method named collect
and moves on to trying to parse the argument passed to the method. But since you're creating a Collector
there's a problem and it ...Object
for toMap
which means it infers the argument(s) to be a Function<Object, Object>
. That makes index
an Object
and thus the error when trying to use it to access an array element. But if you were to simply change index -> headerDisplayName[index]
to (Integer index) -> headerDisplayName[index]
that part of the code would start working. And then you would see that the underlying error is trying to pass a Collector
to the IntStream#collect(Supplier,ObjIntStream,BiConsumer)
method.
IntStream
doesn't have a#collect(Collector)
method.