31
Элементы функционального программирования Алексей Владыкин 20 октября 2014 Алексей Владыкин Функциональное программирование 20 октября 2014 1 / 31

07 - Java. Элементы функционального программирования в Java

Embed Size (px)

Citation preview

Page 1: 07 - Java. Элементы функционального программирования в Java

Элементы функционального программирования

Алексей Владыкин

20 октября 2014

Алексей Владыкин Функциональное программирование 20 октября 2014 1 / 31

Page 2: 07 - Java. Элементы функционального программирования в Java

1 Особенности ФП

2 Функциональные интерфейсы

3 𝜆-выражения

4 Ссылки на методы

5 Stream API

Алексей Владыкин Функциональное программирование 20 октября 2014 2 / 31

Page 3: 07 - Java. Элементы функционального программирования в Java

Особенности ФП

https://xkcd.com/1270/

Алексей Владыкин Функциональное программирование 20 октября 2014 3 / 31

Page 4: 07 - Java. Элементы функционального программирования в Java

Особенности ФП

Функциональные языки

LISP + диалекты

Erlang

F#

Haskell

и другие

Алексей Владыкин Функциональное программирование 20 октября 2014 4 / 31

Page 5: 07 - Java. Элементы функционального программирования в Java

Особенности ФП

Процесс вычисления представляет собой вычисление значенияфункции (в математическом смысле)

Функции высших порядков

𝜆-выражения

Ленивые вычисления

Алексей Владыкин Функциональное программирование 20 октября 2014 5 / 31

Page 6: 07 - Java. Элементы функционального программирования в Java

Функциональные интерфейсы

Алексей Владыкин Функциональное программирование 20 октября 2014 6 / 31

Page 7: 07 - Java. Элементы функционального программирования в Java

Функциональные интерфейсы

Функции представляются объектами

Один из методов объекта вычисляет значение функции

Интерфейсы для наиболее распространенных функций собраны впакете java.util.function

Такие интерфейсы с единственным абстрактным методомназываются функциональными и помечаются аннотацией@FunctionalInterface

Алексей Владыкин Функциональное программирование 20 октября 2014 7 / 31

Page 8: 07 - Java. Элементы функционального программирования в Java

Функциональные интерфейсы

package java.util.function;

@FunctionalInterfacepublic interface Predicate <T> {

boolean test(T t);

default Predicate <T> negate () {// ...

}

// and , or}

Алексей Владыкин Функциональное программирование 20 октября 2014 8 / 31

Page 9: 07 - Java. Элементы функционального программирования в Java

Функциональные интерфейсы

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

Page 10: 07 - Java. Элементы функционального программирования в Java

Функциональные интерфейсы

package java.util.function;

@FunctionalInterfacepublic interface Supplier <T> {

T get ();}

Алексей Владыкин Функциональное программирование 20 октября 2014 10 / 31

Page 11: 07 - Java. Элементы функционального программирования в Java

Функциональные интерфейсы

package java.util.function;

@FunctionalInterfacepublic interface Consumer <T> {

void accept(T t);

default Consumer <T> andThen(Consumer <? super T> after) {

// ...}

}

Алексей Владыкин Функциональное программирование 20 октября 2014 11 / 31

Page 12: 07 - Java. Элементы функционального программирования в Java

Функциональные интерфейсы

package java.util;

@FunctionalInterfacepublic interface Comparator <T> {

int compare(T o1, T o2);

// ...}

Алексей Владыкин Функциональное программирование 20 октября 2014 12 / 31

Page 13: 07 - Java. Элементы функционального программирования в Java

Функциональные интерфейсы

find(Predicate<T> predicate)

sort(Comparator<T> order)

forEach(Consumer<T> action)

map(Function<T, R> func)

Алексей Владыкин Функциональное программирование 20 октября 2014 13 / 31

Page 14: 07 - Java. Элементы функционального программирования в Java

Функциональные интерфейсы

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

Page 15: 07 - Java. Элементы функционального программирования в Java

𝜆-выражения

Алексей Владыкин Функциональное программирование 20 октября 2014 15 / 31

Page 16: 07 - Java. Элементы функционального программирования в Java

𝜆-выражения

Новый компактный синтаксис для инстанцированияфункциональных интерфейсов

List <User > users = getAllUsers ();Collections.sort(users , (u1, u2) ->

u1.getName (). compareTo(u2.getName ()));

Компилятор сам выводит типы

Фигурные скобки не нужны, если внутри одно выражение

Алексей Владыкин Функциональное программирование 20 октября 2014 16 / 31

Page 17: 07 - Java. Элементы функционального программирования в Java

𝜆-выражения

List <User > users = getAllUsers ();Collections.sort(users ,

Comparator.comparing ((u) -> u.getName ()));

Алексей Владыкин Функциональное программирование 20 октября 2014 17 / 31

Page 18: 07 - Java. Элементы функционального программирования в Java

𝜆-выражения

Iterable.forEach()

List <User > users = getAllUsers ();list.forEach ((u) ->

System.out.println(u.getName ()));

Алексей Владыкин Функциональное программирование 20 октября 2014 18 / 31

Page 19: 07 - Java. Элементы функционального программирования в Java

𝜆-выражения

Collection.removeIf()

void removeUserByName(String userName) {List <User > users = getAllUsers ();users.removeIf ((u) ->

u.getName (). equals(userName ));}

Можно обращаться к тем локальным переменным, которые«effectively final»

Алексей Владыкин Функциональное программирование 20 октября 2014 19 / 31

Page 20: 07 - Java. Элементы функционального программирования в Java

𝜆-выражения

List.replaceAll()

List <String > list = getList ();list.replaceAll ((s) -> {

StringBuilder sb = new StringBuilder(s);return sb.reverse (). toString ();

});

Алексей Владыкин Функциональное программирование 20 октября 2014 20 / 31

Page 21: 07 - Java. Элементы функционального программирования в Java

Ссылки на методы

Еще один способ инстанцирования функциональных интерфейсов:по имени метода

List <Integer > list = getList ();list.forEach(System.out:: println );

Алексей Владыкин Функциональное программирование 20 октября 2014 21 / 31

Page 22: 07 - Java. Элементы функционального программирования в Java

Ссылки на методы

List <User > users = getAllUsers ();Collections.sort(users ,

Comparator.comparing(User:: getName ));

Алексей Владыкин Функциональное программирование 20 октября 2014 22 / 31

Page 23: 07 - Java. Элементы функционального программирования в Java

Ссылки на методы

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

Page 24: 07 - Java. Элементы функционального программирования в Java

Stream API

Алексей Владыкин Функциональное программирование 20 октября 2014 24 / 31

Page 25: 07 - Java. Элементы функционального программирования в Java

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

Page 26: 07 - Java. Элементы функционального программирования в Java

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

Page 27: 07 - Java. Элементы функционального программирования в Java

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

Page 28: 07 - Java. Элементы функционального программирования в Java

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

Page 29: 07 - Java. Элементы функционального программирования в Java

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

Page 30: 07 - Java. Элементы функционального программирования в Java

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

Page 31: 07 - Java. Элементы функционального программирования в Java

Что сегодня узнали

Что такое функциональное программирование

Какие средства добавлены в Java 8 для поддержки ФП

Как писать на Java в функциональном стиле

Алексей Владыкин Функциональное программирование 20 октября 2014 31 / 31