Download - Lambda in Java8
-
Lambda in Java
Olena Syrota, Kyiv
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
Functional interface example:
interface Runnable { void run(); }
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 list = new ArrayList();
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
interface Collection {
forEach(Block action) default {
for (T t: this) {
action.apply(t);
}
}
}
Block, Predicate - 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 { forEach(Block action) default { for (T t: this) { action.apply(t); } } boolean removeAll default ( Predicate
-
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);
}
shapes.filter(s->s.getColor()==RED)
.forEach(s->{s.setColor(BLUE);});
-
Bulk operations on Collections (cont.)
Select blue shapes to list
List 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 hasBlueBlock =
shapes.filter(s->s.getColor()==RED)
.map (s->s.getContainer())
.into(new HashSet ());
-
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))
Iterable fooIter = collection;
Iterable filtered = fooIter.filter(f->f.isBlue());
Iterable mapped = filtered.map(f->g.getContainer());
mapped.forEach(s->System.out.println(s));
It is possible to pass behavior to these methods because of functional interfaces
Predicate, Mapper , Block defined in Java 8
Lambda-style
Java-style
Interface Iterable was widen
-
Predicate public interface Predicate {
boolean test(T t);
Predicate and(Predicate
-
Mapper
public interface Mapper {
U map(T t);
public Mapper compose(
Mapper
-
Block
public interface Block {
void apply(T t);
}
-
Example of Predicate functional interface and default-methods
Predicate pr1 = f -> f==null;
Predicate pr2 = f -> f.isEmpty();
List list = new ArrayList();
// ... add elements to list
List listRes = new ArrayList();
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 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 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;
Equivalent Runnable r1 = System.out::println;
Runnable r2 = () -> { System.out.println(); }
-
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 {
int compare (T o1, T o2);
Comparator reverse () default {
return (o1, o2)->compare (o2, o1);
}
Comparator compose (Comparator other) default {
return (o1, o2) -> { int cmp = compare (o1, o2);
return cmp!=0?cmp:other.compare(o1, o2);
};
}
}
Reversing of comparison order
Combining comparison
functions
Comparator byFirst =
Comparator byLast =
Comparator byFirstLast = byFirst.compose(byLast);
Comparator byLastDesc = byLast.reverse();
-
Sorting with lambda
class Comparators {
public static
-
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/closures-closure-is-form-of-anonymous_28.html
Brian Goetz, The Road to Lambda, https://oracleus.activeevents.com/connect/sessionDetail.ww?SESSION_ID=4862
http://www.jcp.org/en/jsr/summary?id=335
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html