Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping Java 8 Stream to elements' method reference

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());
like image 863
mkvcvc Avatar asked Feb 06 '23 09:02

mkvcvc


2 Answers

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]
like image 154
Eran Avatar answered Feb 19 '23 20:02

Eran


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.

like image 32
Tagir Valeev Avatar answered Feb 19 '23 21:02

Tagir Valeev