Let's say I have an interface like this:
public interface Service {
List<Result> getResults();
// some other methods
}
I have a List
of implementations of that interface in List<Service> services
.
How do I transform that List
into a List
of method references to the getResults
method (or even better: a List
of Supplier<List<Result>>
) dynamically?
I was looking for something akin to
List<Supplier<List<Result>>> = services.stream()
.map(s -> s::getResults)
.collect(Collectors.toList());
It seems the compiler needs some help with type inference.
List<Supplier<List<Result>>> list =
services.stream()
.map(s -> (Supplier<List<Result>>)(() -> s.getResults()))
.collect(Collectors.toList());
Here's a working example which replaces your Service
interface with StringBuilder
and your Result
with String
. I'm using Arrays.asList(s.toString().split(" "))
to produce a List<String>
from each StringBuilder
.
List<StringBuilder> services = new ArrayList<>();
services.add (new StringBuilder());
services.add (new StringBuilder());
services.get (0).append ("one two three");
services.get (1).append ("four five six");
List<Supplier<List<String>>> list =
services.stream()
.map(s -> (Supplier<List<String>>) (() -> Arrays.asList(s.toString().split(" "))))
.collect(Collectors.toList());
System.out.println (list.get (0).get ());
System.out.println (list.get (1).get ());
Output :
[one, two, three]
[four, five, six]
Method references have no particular type (they can be mapped to various functional interfaces, for example Supplier
or Callable
), so you have to add a hint to the compiler, when the type can’t be inferred. Casting is one possibility, but I prefer explicit generic argument:
List<Supplier<List<Result>>> list = services.stream()
.<Supplier<List<Result>>>map(s -> s::getResults)
.collect(Collectors.toList());
In general there's no restriction on using method references inside lambda expressions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With