Transcript
Discovering Lambdas in Discovering Lambdas in Java8Java8
by Aleksandra Dmytrenkoby Aleksandra Dmytrenko
ПланПланСтарая добрая Java -> Функциональное программирование
Как посчитать факториал?
Слон и моська в одном
Функциональные интерфейсы
ФункциональноФункциональное е
программировапрограммирование!ние!
Чем ФП приятно?Чем ФП приятно?Функция не может поменять значение переменной вне своей видимости, все переменные final (рай для юнит тестов)
Внешние состояние не влияет на функцию (удобно отлаживать и замещать части кода).
Встроенная многопоточность (кому нравится думать про «разделяй и властвуй?»)
Ленивые (отложенные) вычисления - выполняется только нужный код в момент, когда надо результат.
Чем ФП чревато?Чем ФП чревато?Состояние не хранится (нет переменных)
Все переменные final или const, нет public (как вам код с такими ограничениями?)
Встроенная многопоточность (к сожалению пока не на высшем уровне)
Ленивые (отложенные) вычисления - выполняется только используемый код в «когда захочу» момент. Тяжело контролировать очередность действий.
К делуК делу
Как определить, Как определить, простое ли число?простое ли число?
Легким Легким движением движением
руки руки императивное императивное программиро-программиро-
вание вание превращается превращается
в в декларативнодекларативно
ее
КАК делаем -> ЧТО КАК делаем -> ЧТО делаем?делаем?
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);}
Добавим проверку Добавим проверку на знак числана знак числа
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);}
Ну… надо бы еще на Ну… надо бы еще на что-то посмотретьчто-то посмотреть
Кого на собеседовании не Кого на собеседовании не просили посчитать просили посчитать
факториал?факториал?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 строчек!
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 строчки!
– Я и многие другие
“Не делайте что-то только потому, что вы можете это сделать. Делайте
красиво.”
Chuck Norris can do Chuck Norris can do multiple inheritance in multiple inheritance in
JavaJava
Я скажу вам Я скажу вам больше, не больше, не только он только он
может. Вы тоже! может. Вы тоже! С помощью С помощью
интерфейсов, интерфейсов, правда.правда.
А что если бы Cлон был Моськой, а А что если бы Cлон был Моськой, а Моська Cлоном?Моська Cлоном?
interface Elephant { default String makeSound(String name) { return name + ": Не злите меня!"; }}
interface Dog { default String makeSound(String name) { return name + ": Гав-гав"; }}
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лоном?
СлонСлон: Не злите меня!: Не злите меня!МоськаМоська: Гав-гав: Гав-гавМоськаМоська--слонслон: Я : Я спокоенспокоен
Множественное наследование - это когда есть дефолтная реализация метода с одинаковым названием в
каждом интерфейсе.А как себя будут вести статические и
абстрактные методы?
Статические методыСтатические методыК ним мы обращаемся как НазваниеКласса.имяМетода. По сути эта комбинация всегда уникальна и ее можно воспринимать целиком, как название
interface Dog {
static String walk() { return "Я бегаю быстренько своими маленькими лапками.»; }}
interface Elephant {
static String walk() { return "Я большой и ступаю тихо но тяжело."; }}—————————————————————————————————————System.out.println(Elephant.walk());System.out.println(Dog.walk());
OUTPUT:
Я большой и ступаю тихо но тяжело.Я бегаю быстренько своими маленькими лапками.
Абстрактные Абстрактные методыметоды
Когда мы инстанциируем абстрактный класс (интерфейс), то надо реализовать все абстрактные методы.
Но если мы имплементируем интерфейсы с одинаковыми названиями методов, достаточно описать только один из них.
Пример: Comparator с его int compare(T o1, T o2), Comparable с его int compareTo(T o)
и другие
Интерфейс, у которого есть только один абстрактный метод называется функциональным интерфейсом
1. Можно по-старинке:Elephant e = new Elephant() { @Override public boolean isProud() { return false; }};
2. Можно по-модному:Elephant e = () -> { return false; };
3. А можно без лишних слов:Elephant e = () -> false;
Реализуем Реализуем функциональный функциональный
интерфейсинтерфейс
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
Функциональный Функциональный интерфейс вызываем интерфейс вызываем
точно так жеточно так же
Подробнее проПодробнее про
ПредикатыПредикаты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), почему нигде нет этого названия?
Подробнее проПодробнее про
ФункцииФункции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;}
В отличие от В отличие от предикатов, предикатов,
возвращают тип, возвращают тип, указанный на указанный на
последнем месте последнем месте и принимает и принимает
типы, указанные типы, указанные вначалевначале
Как применяем Как применяем предикатыпредикаты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());
Нету параметра. Нету параметра. Стрим сам Стрим сам передает.передает.
Как применяем Как применяем функции?функции?
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()
Подробнее проПодробнее про
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
Подробнее проПодробнее про
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(); }
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
Это совсем не Это совсем не все, но основное, все, но основное, что надо знать о что надо знать о
JavaJava
Тут код с презентации и слайдыhttps://github.com/olexandra-dmytrenko/LambdasForConfs.git
Спасибо за Спасибо за внимание :)внимание :)
top related