Lambdas
Что под капотом
Functional interface — only one abstract method (has functional descriptor)
4 основных — Supplier, Consumer, Predicate, Function
Типы lambda
Consumer<T>: Consumer<String> sampleConsumer = System.out::println;
Predicate<T>: Predicate<String> samplePredicate = (String s) -> s.isEmpty();
BiPredicate<T, U>: BiPredicate<String,String> sampleBiPredicate = (String s1, String s2) -> s1.equals(s2);
Supplier<T>: Supplier<Apple> apConstructor = Apple::new;
Function<T, R>: Function<Apple, Int> getWeight = Apple::getWeight;
BiFunction<T,U,R>: BiFunction<Int, Color, Apple> constructorWith2Args = Apple::new;
UnaryOperator<T>: UnaryOperator<Apple> newGreenApple = (apple) -> new Apple(apple.getWeight(), Color.GREEN);
BinaryOperator<T>: BinaryOperator<Apple> newGreenApple = (apple, weight) -> new Apple(weight.getWeight(), apple.getColor());
BiConsumer<T, U>:
Для трех примитивных типов — int, long, double — отдельные типы
Method references
- Static methods of class —
(arg0) -> ClassName::static
- Instance metthod of class —
(str) - > str.length() => String::length
- method of variable — str::toUpperCase()
- constructor reference =
Supplier<Apple> aps = Apple::new;
MethodReferenceChain.getStream()::ordered() — > store reference to Stream and used it again. Repeat call ends with error.
Composing Lambdas
For Function type =
andThen, compose
For Predicate =
negate, or, and
For Comparator =
reversed, thenComparing(Int, Long, Double)
Testing
1) Testing if lambda in field
2) Testing lambda behavior
3) Extract lambda code in method and use method reference
4) High-order — change lambda in parameters and test it
Patterns
1) Strategy — functional interface, instance — lambdas
2) Template method — add parameter for lambda
3) Observer — if implementation of Observer is simple without fields -> can change with lambdas
4) Chain of responsibility — composite lambdas
5) Factory — ? map of name of product with function/method reference for constructor
Capture variables
instance variables and static variables — without restriction (instance variables — like capturing final variable this)
Local variables == final or effectively final (assigned only ones).
Instance variables are stored on the heap, whereas local variables live on the stack.
Java implements access to a free local variable as access to a copy of it, rather than access to the original variable.