Lev Dubinets
Lev Dubinets

Reputation: 808

Composing Java 8 method references in stream collector

I would like to compose method references in a stream's collect(Collectors.toMap(..)) call. In the following example, I have code that accomplishes my task without a method reference:

class A {
    private String property1;
    private B property2;

    public String getProperty1() { return property1; }
    public B getProperty2() { return property2; }
}

class B {
    private String property3;

    public String getProperty3() { return property3; }
}

public class Main {
    public static void Main() {
        List<A> listOfA = /* get list */;

        Map<String, String> = listOfA.stream()
            .collect(toMap(x -> x.getProperty1(), x -> x.getProperty2().getProperty3()));
    } 
}

It is trivial to change x -> x.getProperty1() to A::getProperty1(). However it is not as trivial with x -> x.getProperty2().getProperty3(). I would like one of the following to work:

.collect(toMap(A::getProperty1, ((Function)A::getProperty2).andThen((Function)B::getProperty3)))

or

.collect(toMap(A::getProperty1, ((Function)B::getProperty3).compose((Function)A::getProperty2)))

However, they both give me the error Non-static method cannot be referenced from static context.

Upvotes: 4

Views: 1742

Answers (1)

ericbn
ericbn

Reputation: 10948

A::getProperty2 is a Function<A, B> (that is a Function that takes an instance of A and returns an instance of B).

You can cast and compose it as:

((Function<A, B>)A::getProperty2).andThen(B::getProperty3)

Or you can create a Function producer like:

public static <A, B, R> Function<A, R> compose(
        Function<A, B> f1, Function<B, R> f2) {
    return f1.andThen(f2);
}

And use it to compose as:

compose(A::getProperty2, B::getProperty3)

Upvotes: 4

Related Questions