You are on page 1of 43

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<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

interface Collection<T> {
forEach(Block<T> action) default {
for (T t: this) {
action.apply(t);
}
}
}

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);
}

shapes.filter(s->s.getColor()==RED)
.forEach(s->{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))





Iterable<Foo> fooIter = collection;
Iterable<Foo> filtered = fooIter.filter(f->f.isBlue());
Iterable<Foo> 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<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;

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<T> {

int compare (T o1, T o2);

Comparator<T> reverse () default {
return (o1, o2)->compare (o2, o1);
}
Comparator<T> compose (Comparator<T> 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<Person> byFirst =
Comparator<Person> byLast =

Comparator<Person> byFirstLast = byFirst.compose(byLast);
Comparator<Person> byLastDesc = byLast.reverse();

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));
}

Usage:
Comparator<Person> byLastName =
Comparators.comparing(p->p.getLastName());
Collections.sort(people, byLastName);


people.sort(Comparators.comparing(p->p.getLastName()))
people.sort(Comparators.comparing(p->p.getLastName()).reverse())

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

You might also like