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
I use a lot of collector blocks where I create an empty Array and fill it using a loop so I decided I need a utility class of my own not to write the same lines again ad again, here it is:
public class Collections {
public static <T, O> List<T> collect(Set<O> items, Function<? super O, ? extends T> mapper) {
return items.stream().map(mapper).collect(Collectors.toCollection(ArrayList::new));
}
}
and use it like this
List<Product> prods = Collections.collect(basket.getOrderItems(), OrderItem::getProduct);
or like this
List<Long> prods = Collections.collect(basket.getOrderItems(), (item)->item.getProduct().getId());
Though it might look like much more easier to read, it seems streams are a little slower in these kind of scenarios, look here
The issue is that Collectors.toList, not surprisingly, returns a List<T>
. Not an ArrayList
.
List<Long> 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 newList
. There are no guarantees on the type, mutability, serializability, or thread-safety of theList
returned; if more control over the returned List is required, usetoCollection(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<Long> 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<Long> ids = remove.stream()
.map(MyObj::getId)
.collect(toCollection(ArrayList::new));