discovering lambdas (speech)

37
Discovering Lambdas Discovering Lambdas in Java8 in Java8 by Aleksandra Dmytrenko by Aleksandra Dmytrenko

Upload: olexandra-dmytrenko

Post on 14-Feb-2017

52 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Discovering Lambdas (Speech)

Discovering Lambdas in Discovering Lambdas in Java8Java8

by Aleksandra Dmytrenkoby Aleksandra Dmytrenko

Page 2: Discovering Lambdas (Speech)

ПланПланСтарая добрая Java -> Функциональное программирование

Как посчитать факториал?

Слон и моська в одном

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

Page 3: Discovering Lambdas (Speech)

ФункциональноФункциональное е

программировапрограммирование!ние!

Page 4: Discovering Lambdas (Speech)

Чем ФП приятно?Чем ФП приятно?Функция не может поменять значение переменной вне своей видимости, все переменные final (рай для юнит тестов)

Внешние состояние не влияет на функцию (удобно отлаживать и замещать части кода).

Встроенная многопоточность (кому нравится думать про «разделяй и властвуй?»)

Ленивые (отложенные) вычисления - выполняется только нужный код в момент, когда надо результат.

Page 5: Discovering Lambdas (Speech)

Чем ФП чревато?Чем ФП чревато?Состояние не хранится (нет переменных)

Все переменные final или const, нет public (как вам код с такими ограничениями?)

Встроенная многопоточность (к сожалению пока не на высшем уровне)

Ленивые (отложенные) вычисления - выполняется только используемый код в «когда захочу» момент. Тяжело контролировать очередность действий.

Page 6: Discovering Lambdas (Speech)

К делуК делу

Page 7: Discovering Lambdas (Speech)

Как определить, Как определить, простое ли число?простое ли число?

Page 8: Discovering Lambdas (Speech)

Легким Легким движением движением

руки руки императивное императивное программиро-программиро-

вание вание превращается превращается

в в декларативнодекларативно

ее

Page 9: Discovering Lambdas (Speech)

КАК делаем -> ЧТО КАК делаем -> ЧТО делаем?делаем?

Imperative style:public boolean isPrime(int number) { for (int curNumb = 2; curNumb <= number/2; curNumb++) { if (number % curNumb == 0) { return false; } } return true;}

DECLARATIVE STYLE:public boolean isPrimeDeclarative(final int number) { return IntStream.rangeClosed(2, number/2) .noneMatch(curNumb -> number % curNumb == 0);}

Page 10: Discovering Lambdas (Speech)

Добавим проверку Добавим проверку на знак числана знак числа

public boolean isPrimeImperative(int number) { if (number < 0) { return false; } for (int curNumb = 2; curNumb <= number / 2; curNumb++) { if (number % curNumb == 0) { return false; } } return true;}

public boolean isPrimeDeclarativeNegativeNumbCheck(final int number) { return number >= 0 && IntStream.rangeClosed(2, number.2).noneMatch(curNumb -> number % curNumb == 0);}

Page 11: Discovering Lambdas (Speech)

Ну… надо бы еще на Ну… надо бы еще на что-то посмотретьчто-то посмотреть

Page 12: Discovering Lambdas (Speech)

Кого на собеседовании не Кого на собеседовании не просили посчитать просили посчитать

факториал?факториал?public static int factorialOf(int number) { if (number >= 0) { int factorial = 1; for (int curNumb = 2; curNumb <= number; curNumb++){ factorial = factorial * curNumber; } return factorial; } else throw new IllegalArgumentException("Factorial can be counted only of not negative numbers.");}

6 строчек!

Page 13: Discovering Lambdas (Speech)

public static int factorialOf(int number) { if (number > 0) return number*factorialOf(number-1); if (number == 0) return 1; else throw new IllegalArgumentException("Factorial can be counted only of not negative numbers.");}

3 строчки!

Факториал через цикл Факториал через цикл каждый напишет. А каждый напишет. А

рекурсия во что обойдется?рекурсия во что обойдется?

public static int factorialOf(int number) { if (number >= 0) return IntStream.rangeClosed(2, number) .reduce(1, (accResult, curNumb) -> accResult * curNumb); else throw new IllegalArgumentException("Factorial can be counted only of not negative numbers.");}

3 строчки!

Page 14: Discovering Lambdas (Speech)

– Я и многие другие

“Не делайте что-то только потому, что вы можете это сделать. Делайте

красиво.”

Page 15: Discovering Lambdas (Speech)

Chuck Norris can do Chuck Norris can do multiple inheritance in multiple inheritance in

JavaJava

Page 16: Discovering Lambdas (Speech)

Я скажу вам Я скажу вам больше, не больше, не только он только он

может. Вы тоже! может. Вы тоже! С помощью С помощью

интерфейсов, интерфейсов, правда.правда.

Page 17: Discovering Lambdas (Speech)

А что если бы Cлон был Моськой, а А что если бы Cлон был Моськой, а Моська Cлоном?Моська Cлоном?

interface Elephant { default String makeSound(String name) { return name + ": Не злите меня!"; }}

interface Dog { default String makeSound(String name) { return name + ": Гав-гав"; }}

Page 18: Discovering Lambdas (Speech)

class EveryDogWantsToBeAnElephant implements Dog, Elephant {@Overridepublic String makeSound(String name) { return name + ": Я спокоен";}public static void main(final String[] args) { EveryDogWantsToBeAnElephant elephantDog = new EveryDogWantsToBeAnElephant(); Elephant e = new Elephant(){}; Dog d = new Dog(){}; System.out.println(e.makeSound("Слон")); System.out.println(d.makeSound("Моська")); System.out.println(elephantDog.makeSound("Моська-слон"));}}

А что если бы Cлон был Моськой, а А что если бы Cлон был Моськой, а Моська Cлоном?Моська Cлоном?

СлонСлон: Не злите меня!: Не злите меня!МоськаМоська: Гав-гав: Гав-гавМоськаМоська--слонслон: Я : Я спокоенспокоен

Page 19: Discovering Lambdas (Speech)

Множественное наследование - это когда есть дефолтная реализация метода с одинаковым названием в

каждом интерфейсе.А как себя будут вести статические и

абстрактные методы?

Page 20: Discovering Lambdas (Speech)

Статические методыСтатические методыК ним мы обращаемся как НазваниеКласса.имяМетода. По сути эта комбинация всегда уникальна и ее можно воспринимать целиком, как название

interface Dog {

static String walk() { return "Я бегаю быстренько своими маленькими лапками.»; }}

interface Elephant {

static String walk() { return "Я большой и ступаю тихо но тяжело."; }}—————————————————————————————————————System.out.println(Elephant.walk());System.out.println(Dog.walk());

OUTPUT:

Я большой и ступаю тихо но тяжело.Я бегаю быстренько своими маленькими лапками.

Page 21: Discovering Lambdas (Speech)

Абстрактные Абстрактные методыметоды

Когда мы инстанциируем абстрактный класс (интерфейс), то надо реализовать все абстрактные методы.

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

Page 22: Discovering Lambdas (Speech)

Пример: Comparator с его int compare(T o1, T o2), Comparable с его int compareTo(T o)

и другие

Интерфейс, у которого есть только один абстрактный метод называется функциональным интерфейсом

Page 23: Discovering Lambdas (Speech)

1. Можно по-старинке:Elephant e = new Elephant() { @Override public boolean isProud() { return false; }};

2. Можно по-модному:Elephant e = () -> { return false; };

3. А можно без лишних слов:Elephant e = () -> false;

Реализуем Реализуем функциональный функциональный

интерфейсинтерфейс

Page 24: Discovering Lambdas (Speech)

interface Elephant { boolean isProud();}

interface Dog { boolean isProud();}

System.out.println("Слон горделив: " + e.isProud());System.out.println("Моська горделива: " + d.isProud());System.out.println("Моська-слон горделив: " + elephantDog.isProud());

OUTPUT:Слон горделив: falseМоська горделива: trueМоська-слон горделив: false

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

точно так жеточно так же

Page 25: Discovering Lambdas (Speech)

Подробнее проПодробнее про

Page 26: Discovering Lambdas (Speech)

ПредикатыПредикаты1. Обычный предикат:

public Predicate<Integer> isGreaterThan2New() { return a -> a > 2;}Как это выглядело раньше:public boolean isGreaterThan2Old(Integer a) { return a > 2;}

2. Обычный би-предикат:public BiPredicate<Integer, Integer> isGreaterThanFunc() { return (a, b) -> a > b;}

Как это выглядело раньше:public boolean isGreaterThan(Integer a, Integer b) { return a > b;}

Всегда Всегда возвращают возвращают

булеан, булеан, реализуют реализуют

интерфейс с интерфейс с методомметодом

boolean boolean testtest((T T t)t);;

Если реализуется метод boolean test(T Если реализуется метод boolean test(T t), почему нигде нет этого названия?t), почему нигде нет этого названия?

Page 27: Discovering Lambdas (Speech)

Подробнее проПодробнее про

Page 28: Discovering Lambdas (Speech)

ФункцииФункции1. Обычный предикат:

public Function<Integer, Integer> multiplyFuncBy2() { return (a) -> a * 2;}Как это выглядело раньше:public Integer multiplyBy2(Integer a) { return a * 2;}

2. Обычный би-предикат:public BiFunction<Integer, Integer, Integer> multiplyFuncBy() { return (a, b) -> a * b;}Как это выглядело раньше:public Integer multiplyFuncBy(Integer a, Integer b) { return a * b;}

В отличие от В отличие от предикатов, предикатов,

возвращают тип, возвращают тип, указанный на указанный на

последнем месте последнем месте и принимает и принимает

типы, указанные типы, указанные вначалевначале

Page 29: Discovering Lambdas (Speech)

Как применяем Как применяем предикатыпредикаты1. Обычный и би-предикат, аналогичные

методы:boolean actual = p.isGreaterThan2New().test(4);boolean actual = p.isGreaterThan2Old(4);p.isGreaterThanNew().test(4, 8);p.isGreaterThanOld(4, 8);

2. Предикат и соответствующий метод в стриме:values.stream().filter(p.isGreaterThan2New( )).collect(Collectors.toList());List<Integer> actual = values.stream().filter(v -> p.isGreaterThan2(v)).collect(Collectors.toList());

Нету параметра. Нету параметра. Стрим сам Стрим сам передает.передает.

Page 30: Discovering Lambdas (Speech)

Как применяем Как применяем функции?функции?

1. Обычная и би-функция, аналогичные методы:int actual = f.multiplyFuncBy2().apply(5);int actual = f.multiplyBy2(5);f.multiplyFuncBy().apply(5, 3);f.multiplyBy(5, 3);

2. Функция и соответствующий метод в стриме: values.stream().map(f.multiplyFuncBy2()).skip(2).limit(2).collect(Collectors.toList());List<Integer> actual = values.stream().map(v -> f.multiplyFuncBy().apply(v, 3)).skip(2).limit(2).collect(Collectors.toList());

Параметр Параметр передается через передается через

apply()apply()

Page 31: Discovering Lambdas (Speech)

Подробнее проПодробнее про

Page 32: Discovering Lambdas (Speech)

Consumer - Consumer - потребительпотребитель

1.Обычный void метод превращается в консьюмер:public <T> void useConsumer(T t){ System.out.print("Consumer says: " + t);}public <T> Consumer<T> useConsumerFunc(){ return (t) -> System.out.print("Consumer says: " + t);}

2.Разница в использовании:consumer.useConsumer("Hello ;)"); consumer.useConsumerFunc().accept("Hello ;)");

3.Использование консьюмера в стриме: Stream.of(1, 6).forEach(consumer.useConsumerFunc() .andThen(l -> System.out.print("\n")));OUTPUT:

Consumer says: 1Consumer says: 6

Page 33: Discovering Lambdas (Speech)

Подробнее проПодробнее про

Page 34: Discovering Lambdas (Speech)

Supplier - поставщикSupplier - поставщик1. 2 метода - обычный и поставщик

public String useSupplier() { return Thread.currentThread().getStackTrace()[1].getMethodName(); }

public Supplier<String> useSupplierFunc() { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()); return () -> Thread.currentThread().getStackTrace()[1].getMethodName(); }

Page 35: Discovering Lambdas (Speech)

Supplier - поставщикSupplier - поставщик1. Тесты:

String actual = supplier.useSupplier();String actual = supplier.useSupplierFunc().get();Stream.of("1 ").forEach(n -> System.out.println(n + supplier.useSupplierFunc()));

2. Вывод:1) useSupplier2) useSupplierFunc lambda$useSupplierFunc$03) useSupplierFunc 1 lambdas.functionalInterface.MySupplier$$Lambda$1/1449621165@3d8c7aca

Page 36: Discovering Lambdas (Speech)

Это совсем не Это совсем не все, но основное, все, но основное, что надо знать о что надо знать о

JavaJava

Тут код с презентации и слайдыhttps://github.com/olexandra-dmytrenko/LambdasForConfs.git

Page 37: Discovering Lambdas (Speech)

Спасибо за Спасибо за внимание :)внимание :)