Ste Ste - 8 days ago 4
Java Question

How to get a Supplier from an instance?

I use the stream API from java8 and got the problem when I map an object to another object and pass this object to a method which expects a supplier, I get a compile error. How do I pass this object to the method?

For a better explanation, I wrote following code:

public class SimpleTest {
public static class B{
public static B mapFrom(A a){
return new B(); //transform to b
}
}

public static class A{
}

public static Integer mapToSomethingElseWith(Supplier<B> b){
return 1;
}


public static void example(){
List<A> a = Lists.newArrayList(new A(),new A(),new A());
List<Integer> l = a.stream()
.map(B::mapFrom)
.map(SimpleTest::mapSomethingElseWith); //does not work. Bad return type in method reference: cannot convert java.lang.Integer to R
.collect(Collectors.toList());
}
}


My current (ugly) solution looks like this:

List<Integer> l = a.stream()
.map(B::mapFrom)
.map((b)-> ((Supplier) () -> b) // map to supplier
.map(SimpleTest::mapSomethingElseWith)
.collect(Collectors.toList());


Exists something similar but more expressive?

Answer

When you write :

 List<Integer> l = a.stream()
         .map(B::mapFrom)

You get a Stream<B> as the mapFrom() method returns B :

 public static B mapFrom(A a){...}

Then, you chain the Stream<B> with :

.map(SimpleTest::mapSomethingElseWith); 

mapToSomethingElseWith() is defined as mapToSomethingElseWith(Supplier<B> b).

So, the compiler expects to have a mapToSomethingElseWith() method with as argument Supplier<B> and not B but you pass a B variable to.

A way of solve your problem is using the map() method with an explicit lambda that invokes mapToSomethingElseWith() with a Supplier<B>.

()-> b where b is the argument of type B of the lambda is a Supplier<B>. It takes indeed no arg and it returns a B instance.

You can so write :

map(SimpleTest::mapSomethingElseWith);
  List<Integer> l = a.stream()
     .map(B::mapFrom)          
     .map(b->SimpleTest.mapToSomethingElseWith(()-> b) )
     .collect(Collectors.toList());