Java8: ссылка на метод из другого метода ссылка

Я хочу использовать ссылку на метод, основанную на другом методе ссылки. Это трудно объяснить, поэтому я приведу вам пример:

Person.java

public class Person{
    Person sibling;
    int age;

    public Person(int age){
        this.age = age;
    }

    public void setSibling(Person p){
        this.sibling = p;
    }

    public Person getSibling(){
        return sibling;
    }

    public int getAge(){
        return age;
    }
}

Учитывая список Person s, я хочу использовать ссылки на методы, чтобы получить список их возраста. Я знаю, что это можно сделать следующим образом:

roster.stream().map(p -> p.getSibling().getAge()).collect(Collectors.toList());

Но мне интересно, возможно ли это сделать больше:

roster.stream().map(Person::getSibling::getAge).collect(Collectors.toList());

Это не очень полезно в этом примере, я просто хочу знать, что возможно.

Ответ 1

В этом случае вам нужно использовать две операции map:

roster.stream().map(Person::getSibling).map(Person::getAge).collect(Collectors.toList());

Первый отображает Person его родному брату, а второй отображает Person в его возраст.

Ответ 2

Вы можете использовать Functions.chain() из Eclipse Collections для ссылок на цепочку:

MutableList<Person> roster = Lists.mutable.empty();
MutableList<Integer> ages = 
    roster.collect(Functions.chain(Person::getSibling, Person::getAge));

Если вы не можете изменить список из List

List<Person> roster = Lists.mutable.empty();
List<Integer> ages =
    ListAdapter.adapt(roster).collect(Functions.chain(Person::getSibling, Person::getAge));

Поскольку возраст - int, вы можете избежать бокса, используя IntList:

MutableList<Person> roster = Lists.mutable.empty();
IntList ages = roster.collectInt(Functions.chainInt(Person::getSibling, Person::getAge));

Примечание. Я участвую в коллекциях Eclipse.

Ответ 3

Используйте Function.andThen и, возможно, оберните свою первую ссылку на метод в вызове или произведите.

public static <V, R> Function<V,R> ofFunction(Function<V,R> function) {
    return function;
}

roster.collect(ofFunction(Person::getSibling).andThen(Person::getAge));