2013-11-07 6 views
32

В то время как довольно нетерпеливо ждал выпуск Java 8 и после чтения блестящего 'State of the Lambda' article from Brian Goetz Я заметил, что function composition не был вообще закрыт.Как сделать композицию функции?

В соответствии с приведенной выше статье, в Java 8 следующее должно быть возможно:

// having classes Address and Person 
public class Address { 

    private String country; 

    public String getCountry() { 
     return country; 
    } 
} 

public class Person { 

    private Address address; 

    public Address getAddress() { 
     return address; 
    } 
} 

// we should be able to reference their methods like 
Function<Person, Address> personToAddress = Person::getAddress; 
Function<Address, String> addressToCountry = Address::getCountry; 

Теперь, если я хотел бы сочинить эти две функции имеют функцию отображения Person в стране, как я могу добиться этого в Java 8?

ответ

49

Существует функция интерфейса по умолчанию Function::andThen и Function::compose:

Function<Person, String> toCountry = personToAddress.andThen(addressToCountry); 
+0

Да, на самом деле это то, что я был заинтересован в, таким образом, принимая свой ответ :) – Yura

+5

Только вчера я пытался получить почти точно То же самое, что и у меня, но у меня была функция «IntFunction» --- и у нее нет ничего, кроме «apply». Интересно, почему ... –

14

Существует один недостаток в использовании compose и andThen. У вас должны быть явные переменные, поэтому вы не можете использовать ссылки на методы следующим образом:

(Person::getAddress).andThen(Address::getCountry) 

Он не будет скомпилирован. Как жаль!

Но вы можете определить функцию полезности и использовать его с удовольствием:

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

compose(Person::getAddress, Address::getCountry) 
+4

Хорошая точка - очень жаль, что она не работает так :) Однако можно вызвать метод 'andThen', используя явное приведение к первому методу ссылки:' ((Function ) Person :: getAddress) .andThen (Address: getCountry) '- по-прежнему выглядит уродливо, но это уже однострочный. Также обратите внимание, что тип второго метода ссылки он вычитал автоматически, поэтому нет необходимости в явном приведении – Yura

+6

@Yura, ребята, что случилось с 'Function fn = p -> p.getAddress(). GetCountry();' ? Это меньше, чем использование этого изобретенного 'compose' или даже не работающего' (Person :: getAddress) .andThen (Address :: getCountry) ' –

+2

@TagirValeev yes - вы правы, это еще одно простое решение упомянутой проблемы :) Однако me, 'andThen' и' compose' являются более интересными с точки зрения функционального программирования – Yura

Смежные вопросы