Lets say we have this boring piece of code that we all had to use:
ArrayList ids = new ArrayList();
for (MyObj obj : myList){
ids.add(obj.getId());
}
After switching to Java 8, my IDE is telling me that I can replace this code with collect call, and it auto-generates:
ArrayList ids = myList.stream().map(MyObj::getId).collect(Collectors.toList());
However its giving me this error:
collect(java.util.stream.Collector) in Steam cannot be applied to: (java.util.stream.Collector, capture, java.util.List>)
I tried casting the parameter but its giving me undefined A and R, and the IDE isn't giving any more suggestions.
I'm curious as how can you use collect call in this scenario, and I couldn't find any information that could guide me properly. Can anyone shed a light?
解决方案
The issue is that Collectors.toList, not surprisingly, returns a List. Not an ArrayList.
List ids = remove.stream()
.map(MyObj::getId)
.collect(Collectors.toList());
Program to the interface.
From the documentation:
Returns a Collector that accumulates the input elements into a new
List. There are no guarantees on the type, mutability,
serializability, or thread-safety of the List returned; if more
control over the returned List is required, use
toCollection(Supplier).
Emphasis mine - you cannot even assume that the List returned is mutable, let alone that it is of a specific class. If you want an ArrayList:
ArrayList ids = remove.stream()
.map(MyObj::getId)
.collect(Collectors.toCollection(ArrayList::new));
Note also, that it is customary to use import static with the Java 8 Stream API so adding:
import static java.util.stream.Collectors.toCollection;
(I hate starred import static, it does nothing but pollute the namespace and add confusion. But selective import static, especially with the Java 8 utility classes, can greatly reduce redundant code)
Would result in:
ArrayList ids = remove.stream()
.map(MyObj::getId)
.collect(toCollection(ArrayList::new));