Is there a common shorthand for the following? External dependencies like Guava welcome.
myList.stream().map(Foo::bar).collect(Collectors.toList());
If I had to implement it, it'd be something like:
static <T, U> List<U> mapApply(List<T> list, Function<T, U> function) {
return list.stream().map(function).collect(Collectors.toList());
}
Is there one that works for any Iterable? If not, how would I write one? I started thinking about it like this:
static <T, U, V extends Iterable> V<U> mapApply(V<T> iterable, Function<T, U> function) {
return iterable.stream().map(function).collect(???);
}
In the case Foo::bar
returns an instance of Foo
again, ie. you need to transform T
into T
again, then you can use List::replaceAll
which uses UnaryOperator<T>
, therefore each item is replaced by one of a same type. This solution mutates the original list.
List<String> list = Arrays.asList("John", "Mark", "Pepe");
list.replaceAll(s -> "hello " + s);
If you want to transform T
into R
, all you can do is to either use your current solution with a sequence of stream()
-> map()
-> collect()
method calls or a simple iteration.
A static method wrapping this would do the same as well. Note that you cannot create a Stream
from both Collection
and Iterable
using the same way. Feel free to pass also your custom Collector
.
T
is a generic type of an input Collection
or Iterable
.R
is a generic type of the mapping function result (mapping from T
to R
)From Collection<T>
List<Bar> listBarFromCollection = mapApply(collectionFoo, Foo::bar, Collectors.toList());
static <T, R> List<R> mapApply(Collection<T> collection, Function<T, R> function) {
return collection.stream()
.map(function)
.collect(Collectors.toList());
}
From Iterable<T>
List<Bar> listBarFromIterable = mapApply(iterableFoo, Foo::bar, Collectors.toList());
static <T, R> List<R> mapApply(Iterable<T> iterable, Function<T, R> function) {
return StreamSupport.stream(iterable.spliterator(), false)
.map(function)
.collect(Collectors.toList());
}
... with a Collector
:
If you want to pass a custom Collector
, it would be Collector<R, ?, U> collector
and the return type of the method U
instead of List<R>
. As @Holger pointed out, passing a Collector
to a method would not much differ from calling an actual stream()
-> map()
-> collect()
.