07 - java. Элементы функционального программирования в java
TRANSCRIPT
Элементы функционального программирования
Алексей Владыкин
20 октября 2014
Алексей Владыкин Функциональное программирование 20 октября 2014 1 / 31
1 Особенности ФП
2 Функциональные интерфейсы
3 𝜆-выражения
4 Ссылки на методы
5 Stream API
Алексей Владыкин Функциональное программирование 20 октября 2014 2 / 31
Особенности ФП
https://xkcd.com/1270/
Алексей Владыкин Функциональное программирование 20 октября 2014 3 / 31
Особенности ФП
Функциональные языки
LISP + диалекты
Erlang
F#
Haskell
и другие
Алексей Владыкин Функциональное программирование 20 октября 2014 4 / 31
Особенности ФП
Процесс вычисления представляет собой вычисление значенияфункции (в математическом смысле)
Функции высших порядков
𝜆-выражения
Ленивые вычисления
Алексей Владыкин Функциональное программирование 20 октября 2014 5 / 31
Функциональные интерфейсы
Алексей Владыкин Функциональное программирование 20 октября 2014 6 / 31
Функциональные интерфейсы
Функции представляются объектами
Один из методов объекта вычисляет значение функции
Интерфейсы для наиболее распространенных функций собраны впакете java.util.function
Такие интерфейсы с единственным абстрактным методомназываются функциональными и помечаются аннотацией@FunctionalInterface
Алексей Владыкин Функциональное программирование 20 октября 2014 7 / 31
Функциональные интерфейсы
package java.util.function;
@FunctionalInterfacepublic interface Predicate <T> {
boolean test(T t);
default Predicate <T> negate () {// ...
}
// and , or}
Алексей Владыкин Функциональное программирование 20 октября 2014 8 / 31
Функциональные интерфейсы
package java.util.function;
@FunctionalInterfacepublic interface Function <T, R> {
R apply(T t);
default <V> Function <V, R> compose(Function <? super V, ? extends T> before) {// ...
}
// andThen}
Алексей Владыкин Функциональное программирование 20 октября 2014 9 / 31
Функциональные интерфейсы
package java.util.function;
@FunctionalInterfacepublic interface Supplier <T> {
T get ();}
Алексей Владыкин Функциональное программирование 20 октября 2014 10 / 31
Функциональные интерфейсы
package java.util.function;
@FunctionalInterfacepublic interface Consumer <T> {
void accept(T t);
default Consumer <T> andThen(Consumer <? super T> after) {
// ...}
}
Алексей Владыкин Функциональное программирование 20 октября 2014 11 / 31
Функциональные интерфейсы
package java.util;
@FunctionalInterfacepublic interface Comparator <T> {
int compare(T o1, T o2);
// ...}
Алексей Владыкин Функциональное программирование 20 октября 2014 12 / 31
Функциональные интерфейсы
find(Predicate<T> predicate)
sort(Comparator<T> order)
forEach(Consumer<T> action)
map(Function<T, R> func)
Алексей Владыкин Функциональное программирование 20 октября 2014 13 / 31
Функциональные интерфейсы
List <User > users = getAllUsers ();Collections.sort(users , new Comparator <User >() {
@Overridepublic int compare(User u1, User u2) {
return u1.getName ().compareTo(u2.getName ());
}});
Алексей Владыкин Функциональное программирование 20 октября 2014 14 / 31
𝜆-выражения
Алексей Владыкин Функциональное программирование 20 октября 2014 15 / 31
𝜆-выражения
Новый компактный синтаксис для инстанцированияфункциональных интерфейсов
List <User > users = getAllUsers ();Collections.sort(users , (u1, u2) ->
u1.getName (). compareTo(u2.getName ()));
Компилятор сам выводит типы
Фигурные скобки не нужны, если внутри одно выражение
Алексей Владыкин Функциональное программирование 20 октября 2014 16 / 31
𝜆-выражения
List <User > users = getAllUsers ();Collections.sort(users ,
Comparator.comparing ((u) -> u.getName ()));
Алексей Владыкин Функциональное программирование 20 октября 2014 17 / 31
𝜆-выражения
Iterable.forEach()
List <User > users = getAllUsers ();list.forEach ((u) ->
System.out.println(u.getName ()));
Алексей Владыкин Функциональное программирование 20 октября 2014 18 / 31
𝜆-выражения
Collection.removeIf()
void removeUserByName(String userName) {List <User > users = getAllUsers ();users.removeIf ((u) ->
u.getName (). equals(userName ));}
Можно обращаться к тем локальным переменным, которые«effectively final»
Алексей Владыкин Функциональное программирование 20 октября 2014 19 / 31
𝜆-выражения
List.replaceAll()
List <String > list = getList ();list.replaceAll ((s) -> {
StringBuilder sb = new StringBuilder(s);return sb.reverse (). toString ();
});
Алексей Владыкин Функциональное программирование 20 октября 2014 20 / 31
Ссылки на методы
Еще один способ инстанцирования функциональных интерфейсов:по имени метода
List <Integer > list = getList ();list.forEach(System.out:: println );
Алексей Владыкин Функциональное программирование 20 октября 2014 21 / 31
Ссылки на методы
List <User > users = getAllUsers ();Collections.sort(users ,
Comparator.comparing(User:: getName ));
Алексей Владыкин Функциональное программирование 20 октября 2014 22 / 31
Ссылки на методы
public void example () {List <String > names = Arrays.asList(
"John", "Frank", "Sam");List <User > users = map(names , User::new);
}
public <S, T> List <T> map(List <S> list ,Function <S, T> function) {
List <T> result = new ArrayList <T>(list.size ());list.forEach ((s) ->
result.add(function.apply(s)));return result;
}
Алексей Владыкин Функциональное программирование 20 октября 2014 23 / 31
Stream API
Алексей Владыкин Функциональное программирование 20 октября 2014 24 / 31
Stream API
java.util.stream
Stream — последовательность элементов (возможно, бесконечная)с поддержкой различных преобразований
List <User > users = getAllUsers ();users.stream ()
.filter ((u) -> u.getAge () > 20)
.sorted(Comparator.comparing(User:: getName ))
.limit (3)
.forEach(System.out:: println );
Источник → промежуточные операции → терминальная операция
Алексей Владыкин Функциональное программирование 20 октября 2014 25 / 31
Stream API
Источники Stream’ов
Collection.stream()
Files.walk(Path), Files.list(Path)
BufferedReader.lines()
Stream.iterate(T, UnaryOperator<T>),Stream.generate(Supplier<T>), Stream.of(T...)
Алексей Владыкин Функциональное программирование 20 октября 2014 26 / 31
Stream API
Промежуточные операции
filter(Predicate<T>)
map(Function<T,R>)
flatMap(Function<T,Stream<R>>)
peek(Consumer<T>)
sorted(Comparator<T>)
distinct()
limit(long)
skip(long)
Алексей Владыкин Функциональное программирование 20 октября 2014 27 / 31
Stream API
Терминальные операции
forEach(Consumer<T>)
findFirst(), findAny()allMatch(Predicate<T>), anyMatch(Predicate<T>),noneMatch(Predicate<T>)
reduce(BinaryOperator<T>)
collect(Collector<T>)
min(Comparator<T>), max(Comparator<T>)
Алексей Владыкин Функциональное программирование 20 октября 2014 28 / 31
Stream API
Пример
private static class FibonacciSupplierimplements Supplier <BigDecimal > {
private BigDecimal prev = BigDecimal.ZERO;private BigDecimal next = BigDecimal.ONE;
@Overridepublic BigDecimal get() {
BigDecimal current = next;next = prev.add(current );prev = current;return current;
}}
Алексей Владыкин Функциональное программирование 20 октября 2014 29 / 31
Stream API
Пример
BigDecimal million = new BigDecimal (1 _000_000 );Stream.generate(new FibonacciSupplier ())
.filter ((d) -> d.compareTo(million) >= 0)
.limit (1)
.forEach(System.out:: println );
Алексей Владыкин Функциональное программирование 20 октября 2014 30 / 31
Что сегодня узнали
Что такое функциональное программирование
Какие средства добавлены в Java 8 для поддержки ФП
Как писать на Java в функциональном стиле
Алексей Владыкин Функциональное программирование 20 октября 2014 31 / 31