Lambda in Java: Olena Syrota, Kyiv Pre-Production Java Lab Lead
The document discusses Java 8's introduction of lambda expressions and functional interfaces. Some key points:
- Java 8 will include lambda expressions, default methods in interfaces, and bulk operations on collections using lambda expressions.
- Lambda expressions allow implementing functional interfaces anonymously and passing code as data.
- Default methods and functional interfaces allow behavior to be added to interfaces and for libraries to take control over iteration instead of the client code.
- Bulk operations on collections like filter, map, and reduce allow building complex operations from simple blocks of code, improving readability.
Lambda in Java: Olena Syrota, Kyiv Pre-Production Java Lab Lead
The document discusses Java 8's introduction of lambda expressions and functional interfaces. Some key points:
- Java 8 will include lambda expressions, default methods in interfaces, and bulk operations on collections using lambda expressions.
- Lambda expressions allow implementing functional interfaces anonymously and passing code as data.
- Default methods and functional interfaces allow behavior to be added to interfaces and for libraries to take control over iteration instead of the client code.
- Bulk operations on collections like filter, map, and reduce allow building complex operations from simple blocks of code, improving readability.
Pre-production Java Lab Lead Java 8 Issue is planned for summer of 2013
Java 8 will contain the most significant changes and innovation in Java lambda (closures) Interface evolution (default methods) Evolution of Collections library (bulk operations) Simplified syntax of parallel computation with libraries How to try it OpenJDK 8 Times change 1995 (when Java was born) No support of lambda in most popular languages Today: ++ has lambda C# has lambda Any new language has lambda Lambda-calculus Mathematical definition of mapping (function) square : REAL REAL "+": [REAL REAL] REAL
Lambda calculus introduces definition of function: square x: REAL | x * x means apply function (square) to argument (x) This expression has function body This expression has return type Other function may be arguments (x)
Anonymous form x x*x Definition of function for computation Until Java 8 anonymous classes were used Anonymous class example interface ActionListener { void actionPerformed(ActionEvent a); }
public class Controller {
public init() {
button.addActionListener( new ActionListener() { public void actionPerfored(ActionEvent e) { // do something. } }); } Anonymous class example interface Runnable { void run(); }
Thread t = new Thread (new Runnable() { void run () { System.out.println("hello"); } }); t.start();
What is lambda-expression Lambda-expression is anonymous method with arguments and body
Example (Object o) -> o.toString()
s -> s.length()
(int x, int y) -> x+y
() -> 42
(x, y, z) -> { if (z) return x; else return y; } How to invoke lambda-expression Intuitively it is expected something like this
{ int x -> x + 1 }.invoke(10)
int sum = { int x, int y -> x + y }.invoke(3, 4);
Wrong, in Java 8 it is done in other way How to invoke lambda-expression in Java Via functional interface Functional interface interface with one method
Invoke lambda-expression means to instantiate functional interface
Example of lambda-expression invoking Runnable r = () -> { System.out.println("hello"); }; Thread t = new Thread (r); t.start(); Functional interface examples Functional interface interface ActionListener { void onEvent(Event e); }
Instantiate lambda-expression and pass to function: ActionListener listenr = e -> System.out.println(e.getWhen()); button.addActionListener(listener);
Short syntax: button.addActionListener(e -> System.out.println(e.getWhen()));
Functional interface examples Functional interface interface Sum { int sum(int x, int y); }
Instantiate lambda-expression: Sum sm = (x, y)-> x+y;
Invoke lambda-expression: int z = sm.sum(2, 3);
Code as data Code (behavior) may be passed as an argument
List<String> list = new ArrayList<String>(); list.add("first"); list.add("second"); list.add("third"); list.forEach((String s)->{System.out.println(s);});
What is good in lambda Control is transferred from client to library No need to change language library can be changed
See examples on next slides
External iteration for (Shape s: shapes) { if (s.getColor() == RED) s.setColor(BLUE); } Client control iteration - external iteration Sequential iteration In this code - what and how When client controls iteration Internal iteration shapes.forEach(s->{ if (s.getColor() == RED) s.setColor(BLUE); }); Iteration controlled by library More what, less how Library can use parallelism custom order of iterating lazy calculation
When iteration is controlled by iterator Interface evolution Interface Collection has new method forEach
Block<T>, Predicate<T> - functional interface from Java 8 Default method new feature of language. Virtual method can have default implementation. This allows to transfer control over iteration to library. Multiple inheritance? Dafault-methods allow to add behavior to interface (not state)
Is this multiple inheritance? Java has multiple type inheritance Java will have multiple behavior inheritance No multiple inheritance of state. Ever.
There are resolution rules for multiple behavior inheritance Resolution rules for multiple behavior inheritance Prefer superclass methods to interface methods Prefer more specific interface to less If conflict, concrete class must provide implementation Conflict resolution example interface A { String foo() default {return "A";} }
interface B { String foo() default {return "B";} }
interface C1 extends A, B { // compile error }
interface C2 extends A, B { // ok String foo() default { return A.super.foo();} }
Collection, default-methods With lambda Java Collection Framework became stale. It needed to change. Interface Collection has new methods: forEach removeAll retailAll
You can replace implementation in subclasses. interface Collection<T> { forEach(Block<T> action) default { for (T t: this) { action.apply(t); } }
boolean removeAll default ( Predicate <? Super T> filter) { boolean removed = false; Iterator<E> each = this.iterator(); while(each.hasNext()) { if(filter.test(each.next())) { each.remove(); removed = true; } } return removed; } } Bulk operations on Collections operations: filter map into
Bulk operations on Collections (cont.) Example with Shapes lets apply lambda shapes.forEach(s-> { if (s.getColor() == RED) s.setColor(BLUE); }
Bulk operations on Collections (cont.) Select blue shapes to list List<Shapes> blueBlocks = shapes.filter(s->s.getColor()==RED) .into(new ArrayList());
Let every shape to be in container (Box). Select those containers that contain blue shapes Set<Box> hasBlueBlock = shapes.filter(s->s.getColor()==RED) .map (s->s.getContainer()) .into(new HashSet<Box> ());
Bulk operations on Collections (cont.) Calculate sum of blue shape weight int sumOfWeight = shapes .filter(s->s.getColor()==BLUE) .map(s->getWeight()) .sum();
Advantages of bulk operations We can build complex operation from simple blocks of code Readable code More what, less how Libraries can apply parallelism, Custom order iteration, laziness Iterable collection.filter(f->f.isBlue()) .map (f->g.getContainer()) .foreach(s->System.out.println(s))
It is possible to pass behavior to these methods because of functional interfaces Predicate<T>, Mapper <T,U>, Block<T> defined in Java 8 Lambda-style Java-style Interface Iterable was widen Predicate public interface Predicate<T> { boolean test(T t);
Predicate<T> and(Predicate<? super T> p) default { return t -> this.test(t) && p.test(t); }
Predicate<T> negate() default { return t -> !this.test(t); }
Predicate<T> or(Predicate<? super T> p) default { return t -> this.test(t) || p.test(t); }
Predicate<T> xor(Predicate<? super T> p) default { return t -> this.test(t) ^ p.test(t); } } Code outlined schematically, see JDK 8 Mapper public interface Mapper<T, U> {
U map(T t);
public <V> Mapper<T, V> compose( Mapper<? super U, ? extends V> after) default { return Mappers.chain(this, after); } }
Block public interface Block<T> { void apply(T t); } Example of Predicate functional interface and default-methods Predicate<String> pr1 = f -> f==null; Predicate<String> pr2 = f -> f.isEmpty();
List<String> list = new ArrayList<String>(); // ... add elements to list List<String> listRes = new ArrayList<String>(); list.filter(pr1.or(pr2).negate()) .into(listRes); Task filter non-empty strings with complex predicate. Iterable (cont.) filter map forEach into sorted aggregate (eg. max, sum ) groupBy mapReduce
Example Select author, sum(pages) from documents group by author
Map<String, Integer> map = new HashMap(); for (Document d: document) { String author = d.getAuthor(); Integer sum = map.get(author); if (sum==null) sum=0; map.put(author, sum+d.getPageCount()); }
Map <String, Integer> map = documents.aggregateBy(d->d.getAuthor(), ()->0, (sum, d) ->sum+d.getPageCount()); Method Reference :: Method reference :: introduced both for static and instance methods
Facility to convert from one interface to another Task t = () -> System.out.println("hi"); Runnable r = t::invoke;
Parallelism Libraries can hide syntactic and semantic complexity of parallelism Code for sequential and parallel execution should be more similar in syntax At this moment syntaxes are completely different Code for sequential execution looks very simple Code for parallel execution looks supercompex the complexity of code hides semantic of what we want to calculate
Example int sumOfWeight = shapes .parallel() .filter(s->s.getColor()==BLUE) .map(s->getWeight()) .sum();
Lambda advantages Lambda helps to develop more expressive API Delegate to library to control infrastructure flow Analogy like inversion of control between client code and library More possibilities for optimization More readable code
Sorting (Java-style) Collections.sort(list, new Comparator() { public int compare(Person x, Person y) return x.getLastName().compareTo(y.getLastName()); }) Default-methods - Combinators public interface Comparator<T> {
Sorting with lambda class Comparators { public static <T, U extends Comparable<? Super U>> Comparator<T> comparing(Mapper <T, U> m) { return (x, y)->m.map(x).compareTo(m.map(y)); }
What had been solved to introduce lambda in Java What is the type of lambda-expressions in Java? No functional type in Java How to represent lambda in bytecode? No functional type presentation in method signature in JVM JVM translation http://cr.openjdk.java.net/~briangoetz/lambda/la mbda-translation.html
Bibliography http://tronicek.blogspot.com/2007/12/closur es-closure-is-form-of-anonymous_28.html Brian Goetz, The Road to Lambda, https://oracleus.activeevents.com/connect/se ssionDetail.ww?SESSION_ID=4862 http://www.jcp.org/en/jsr/summary?id=335 http://cr.openjdk.java.net/~briangoetz/lambd a/lambda-translation.html