autumn collections : from iterable to lambdas, streams and collectors

358
#DV13LBDS @JosePaumard Autumn Collections From Iterable to Lambdas, Streams and Collectors

Upload: jose-paumard

Post on 26-Jan-2015

109 views

Category:

Education


1 download

DESCRIPTION

These are the slides of my talk at Devoxx 2013. This presentation introduces the lambda expressions, how we can write them, and what they bring to us developers. The second part presents in details the new patterns introduced by the Stream and Collector APIs. These new APIs will change the way we process large collections content, enabling concurrent and parallel access, with a very simple programming model, and amazing patterns. Complex examples will show how powerful those APIs are, and how they can help us write efficient and clean code.

TRANSCRIPT

Page 1: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Autumn Collections

From Iterable to Lambdas,

Streams and Collectors

Page 2: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 3: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Why were they introduced ?

Page 4: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Why were they introduced ?

Why are they so important ?

Page 5: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Why were they introduced ?

Why are they so important ?

How will they change the way we build

applications ?

Page 6: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 7: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 8: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions ?

#DV13LBDS

Page 9: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Let’s introduce the lambdas

Page 10: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Let’s introduce the lambdas on a simple example

Page 11: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A very simple example

public class Person { private String name ; private int age ; // constructors // getters / setters }

List<Person> list = new ArrayList<>() ;

A plain old bean…

… and a good old list

Page 12: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

int sum = 0 ; // I need a default value in case // the list is empty int average = 0 ; for (Person person : list) { sum += person.getAge() ; } if (!list.isEmpty()) { average = sum / list.size() ; }

Average of the ages

Page 13: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

int sum = 0 ; int n = 0 ; int average = 0 ; for (Person person : list) { if (person.getAge() > 20) { n++ ; sum += person.getAge() ; } } if (n > 0) { average = sum / n ; }

Trickier : average of the ages of people older than 20

Page 14: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Trickier : average of the ages of people older than 20

« imperative programming »

int sum = 0 ; int n = 0 ; int average = 0 ; for (Person person : list) { if (person.getAge() > 20) { n++ ; sum += person.getAge() ; } } if (n > 0) { average = sum / n ; }

Page 15: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

select avg(age) from Person where age > 20

… it does not have to be like that !

This is a description of the result

Page 16: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

select avg(age) from Person where age > 20

… it does not have to be like that !

This is a description of the result

In that case, the DB server is free to compute the

result the way it sees fit

© SQL language, 1974

Page 17: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Person age age > 20 sum

1st step : mapping

map

Page 18: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Person age age > 20 sum

1st step : mapping

Mapping :

- takes a list of a given type

- gives another list of a different type

- same number of elements

map

Page 19: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Person age age > 20 sum

2nd step : filtering

filter map

Page 20: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Person age age > 20 sum

2nd step : filtering

Filtering :

- takes a list of a given type

- gives another list of a the same type

- less elements

filter map

Page 21: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Person age age > 20 sum

3rd step : reduction

reduce filter map

Page 22: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Person age age > 20 sum

3rd step : reduction

Reduction : agregation of all the elements

in a single one

Ex : average, sum, min, max, etc…

reduce filter map

Page 23: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How can I model that ?

Page 24: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 7 way

Create an interface to model the mapper…

public interface Mapper<T, V> { public V map(T t) ; }

Page 25: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

public class PersonToAgeMapper implements Mapper<Person, Integer> { public Integer map(Person p) { return p.getAge() ; } }

The JDK 7 way

… and create an implementation …

public interface Mapper<T, V> { public V map(T t) ; }

Page 26: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Mapper<Person, Integer> mapper = new Mapper<Person, Integer>() { public Integer map(Person p) { return p.getAge() ; } }

The JDK 7 way

… that could be anonymous

public interface Mapper<T, V> { public V map(T t) ; }

Page 27: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 7 way

We can do the same for the filtering

public interface Predicate<T> { public boolean filter(T t) ; }

Page 28: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

public class AgePredicate implements Predicate<Integer> { public boolean filter(Integer i) { return i > 20 ; } }

The JDK 7 way

We can do the same for the filtering

public interface Predicate<T> { public boolean filter(T t) ; }

Page 29: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

AgePredicate predicate = new Predicate<Integer>() { public boolean filter(Integer i) { return i > 20 ; } }

The JDK 7 way

We can do the same for the filtering

public interface Predicate<T> { public boolean filter(T t) ; }

Page 30: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 7 way

And for the reduction

public interface Reducer<T> { public T reduce(T t1, T t2) ; }

Page 31: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

public class Sum implements Reducer<Integer> { public Integer reduce(Integer i1, Integer i2) { return i1 + i2 ; } }

The JDK 7 way

And for the reduction

public interface Reducer<T> { public T reduce(T t1, T t2) ; }

Page 32: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Reducer<Integer> reduction = new Reducer<Integer>() { public Integer reduce(Integer i1, Integer i2) { return i1 + i2 ; } }

The JDK 7 way

And for the reduction

public interface Reducer<T> { public T reduce(T t1, T t2) ; }

Page 33: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 7 way

So the whole map / filter / reduce looks like this

1) Create 3 interfaces public interface Mapper<T, V> { public V map(T t) ; }

public interface Predicate<T> { public boolean filter(T t) ; }

public interface Reducer<T> { public T reduce(T t1, T t2) ; }

Page 34: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 7 way

So the whole map / filter / reduce looks like this

1) Create 3 interfaces

2) Apply the pattern

List<Person> persons = ... ; int sum = persons.map( new Mapper<Person, Integer>() { public Integer map(Person p) { return p.getAge() ; } }) .filter( new Filter<Integer>() { public boolean filter(Integer age) { return age > 20 ; } }) .reduce(0, new Reducer<Integer>() { public Integer recude(Integer i1, Integer i2) { return i1 + i2 ; } } }) ;

Page 35: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 7 way

So the whole map / filter / reduce looks like this

1) Create 3 interfaces

2) Apply the pattern

List<Person> persons = ... ; int sum = persons.map( new Mapper<Person, Integer>() { public Integer map(Person p) { return p.getAge() ; } }) .filter( new Filter<Integer>() { public boolean filter(Integer age) { return age > 20 ; } }) .reduce(0, new Reducer<Integer>() { public Integer recude(Integer i1, Integer i2) { return i1 + i2 ; } } }) ;

Page 36: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 8 way

Page 37: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { return person.getAge() ; } }

The JDK 8 way

Let’s rewrite our mapper

Page 38: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } }

The JDK 8 way

Let’s rewrite our mapper

Page 39: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return p.getAge() ; } }

The JDK 8 way

mapper = Person person ;

we take a

person p

Let’s rewrite our mapper

Page 40: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } }

The JDK 8 way

mapper = Person person -> ;

and then …

Let’s rewrite our mapper

Page 41: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } }

The JDK 8 way

mapper = Person person -> person.getAge() ;

… return the age of p

Let’s rewrite our mapper

Page 42: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Let’s rewrite our mapper

mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } }

The JDK 8 way

mapper = Person person -> person.getAge() ;

Page 43: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Let’s rewrite our mapper

The compiler can recognize this as an implementation of

Mapper

mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } }

The JDK 8 way

mapper = Person person -> person.getAge() ;

Page 44: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

What if …

… there is more than one statement ?

The return has to be explicit

mapper = Person person -> { System.out.println("Mapping " + person) ; return person.getAge() ; }

Page 45: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

What if …

…I have no return value ?

consumer = Person person -> p.setAge(p.getAge() + 1) ;

Page 46: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

What if …

…I have more than one argument ?

Or :

reducer = (int i1, int i2) -> { return i1 + i2 ; }

reducer = (int i1, int i2) -> i1 + i2 ;

Page 47: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 8 way

How can the compiler recognize the implementation of

map() ?

mapper = Person person -> person.getAge() ;

Page 48: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 8 way

How can the compiler recognize the implementation of

map() ?

1) There’s only one method in Mapper

mapper = Person person -> person.getAge() ;

Page 49: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 8 way

How can the compiler recognize the implementation of

map() ?

1) There’s only one method in Mapper

2) Both the parameters and the return types are

compatible

mapper = Person person -> person.getAge() ;

Page 50: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 8 way

How can the compiler recognize the implementation of

map() ?

1) There’s only one method in Mapper

2) Both the parameters and the return types are

compatible

3) Thrown exceptions (if any) are compatible

mapper = Person person -> person.getAge() ;

Page 51: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

More lambdas

Writing more lambdas becomes natural :

mapper = Person person -> person.getAge() ; // mapper filter = int age -> age > 20 ; // filter reducer = (int i1, int i2) -> i1 + i2 ; // reducer

Page 52: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

More lambdas

And most of the time, the compiler understands this :

The « parameter types » can be omitted

mapper = person -> person.getAge() ; // mapper filter = age -> age > 20 ; // filter reducer = (i1, i2) -> i1 + i2 ; // reducer

Page 53: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Just a remark on the reduction

How does it really work ?

Page 54: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 55: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 56: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 57: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 58: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 59: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 60: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 61: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 62: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 63: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 64: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Reduction

2 examples :

Caveat :

the result is always reproductible in serial

it’s not in parallel

Reducer r1 = (i1, i2) -> i1 + i2 ; // Ok Reducer r2 = (i1, i2) -> i1*i1 + i2*i2 ; // Oooops

Page 65: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

So far

A lambda expression is an alternative

to write instances of anonymous inner classes

Page 66: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Other syntaxes

Very often one writes

This syntax is also possible :

mapper = person -> person.getAge() ;

mapper = Person::getAge ; // non static method

Page 67: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Other syntaxes

Other example :

Or :

sum = (i1, i2) -> i1 + i2 ; sum = Integer::sum ; // static method, new !

max = (i1, i2) -> i1 > i2 ? i1 : i2 ; max = Integer::max ; // static method, new !

Page 68: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Other syntaxes

Other example :

toLower = String::toLowerCase ;

// !!!! NO NO NO !!!! toLowerFR = String::toLowerCase(Locale.FRANCE) ;

Page 69: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

More on the lambdas

Page 70: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions :

What model for a lambda ?

Page 71: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions :

What model for a lambda ?

Can I put a lambda in a variable ?

Page 72: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions :

What model for a lambda ?

Can I put a lambda in a variable ?

Is a lambda an object ?

Page 73: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Modelization

A lambda is an instance of a « functional interface »

@FunctionalInterface public interface Consumer<T> { public void accept(T t) ; }

Page 74: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Modelization

A lambda is an instance of a « functional interface »

- only one abstract method (methods from Object dont

count)

- can be annotated by @FunctionalInterface (optional)

@FunctionalInterface public interface Consumer<T> { public void accept(T t) ; }

Page 75: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Modelization

A lambda is an instance of « functional interface »

@FunctionalInterface public interface Consumer<T> { public void accept(T t) ; public default Consumer<T> chain(Consumer<? super T> other) { Objects.requireNonNull(other); return (T t) -> { accept(t); other.accept(t); }; } }

Page 76: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting a lambda in a variable

Example of a consumer

So :

Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ;

Consumer<String> c = s -> System.out.println(s) ;

Page 77: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting a lambda in a variable

Example of a consumer

So :

Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ;

Consumer<String> c = s -> System.out.println(s) ;

Question : what is s ?

Page 78: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting a lambda in a variable

Example of a consumer

So :

Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ;

Consumer<String> c = s -> System.out.println(s) ;

Answer : the compiler

infers that it is a String

Page 79: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting a lambda in a variable

Side question : can one write this ?

int i = ... ; Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println("i = " + i) ; } } ;

Page 80: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting a lambda in a variable

Side question : can one write this ?

JDK 7 : i should be final

int i = ... ; Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println("i = " + i) ; } } ;

Page 81: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting a lambda in a variable

Side question : can one write this ?

JDK 8 : Yes ! (no final needed)

int i = ... ; Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println("i = " + i) ; } } ;

Page 82: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting a lambda in a variable

But this code …

does not compile

int i = ... ; Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println("i = " + i) ; } } ; i = i + 1 ;

Page 83: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting a lambda in a variable

Because i is an effectively final variable

final int i = ... ; Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println("i = " + i) ; } } ; i = i + 1 ; // Cant modify

Page 84: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

And what about this ?

JDK 7 : this is the anonymous instance

Calling accept() will print « I’m in c »

Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println("this = " + this) ; } public String toString() { return "I’m in c" ; } } ;

Page 85: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

And what about this ?

JDK 8 : no change, calling accept() still prints « I’m in c »

But …

Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println("this = " + this) ; } public String toString() { return "I’m in c" ; } } ;

Page 86: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

And what about this ?

Consumer can also be instanced with a lambda

Here this is the enclosing instance

Consumer<String> c = s -> System.out.println(this) ;

Page 87: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions :

What model for a lambda ?

answer : with a functional interface

Can I put a lambda in a variable ?

answer : yes

Is a lambda an object ?

Page 88: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is a lambda an objet ?

Let’s play the game of 7 errors (with only 1 error)

Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ;

Consumer<String> c = s -> System.out.println(s) ;

Page 89: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is a lambda an objet ?

Let’s play the game of 7 errors (with only 1 error)

Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ;

Consumer<String> c = s -> System.out.println(s) ;

Page 90: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions :

What model for a lambda ?

answer : with a functionnal interface

Can I put a lambda in a variable ?

answer : yes

Is a lambda an object ?

answer : no

Page 91: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Plenty of lambdas :

Java.util.functions

Page 92: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java.util.functions

This new package holds the functionnal interfaces

There are 43 of them

Page 93: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java.util.functions

Supplier : alone in its kind

Consumer / BiConsumer

Function / BiFunction (UnaryOperator / BinaryOperator)

Predicate / BiPredicate

Plus the primitive types versions

Page 94: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Supplier

A supplier supplies an object

public interface Supplier<T> { T get() ; }

Page 95: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Consumer

A consumer just … accepts an object

public interface Consumer<T> { void accept(T t) ; }

Consumer<String> c1 = s -> System.out.println(s) ; Consumer<String> c2 = ... ; Consumer<String> c3 = c1.andThen(c2) ; persons.stream().forEach(c3) ;

Page 96: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

BiConsumer

Takes 2 arguments instead of one

Can be chained

Primitive types :

- ObjIntConsumer

- ObjLongConsumer

- ObjDoubleConsumer

ObjIntConsumer takes an object and an int as arguments

Page 97: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Function

A function takes an object and returns another one

Can be chained and / or composed

public interface Function<T, R> { R apply(T t) ; }

Page 98: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

BiFunction

A function that takes 2 arguments

Can be chained

Primitive type versions :

- ToIntBiFunction

- ToLongBiFunction

- ToDoubleBiFunction

Page 99: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

UnaryOperator

A UnaryOperator is a Function that operates on one type

Other UnaryOperators :

- IntUnaryOperator

- LongUnaryOperator

- DoubleUnaryOperator

Page 100: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

BinaryOperator

A BinaryOperator is a BiFunction that operates on one type

Other BinaryOperators :

- IntBinaryOperator

- LongBinaryOperator

- DoubleBinaryOperator

IntBinaryOperator takes 2 int, and returns an int

Page 101: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Predicate

A Predicate takes an object and returns a boolean

Can be negated, composed with and / or

public interface Predicate<T> { boolean test(T t) ; }

Page 102: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

BiPredicate

A BiPredicate takes two object and returns a boolean

public interface BiPredicate<T, U> { boolean test(T t, U u) ; }

Page 103: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Predicate & BiPredicate

Primitive types :

- IntPredicate

- LongPredicate

- DoublePredicate

Not for BiPredicate

Page 104: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions ?

#DV13LBDS

Page 105: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Back to the

map / filter / reduce

pattern

Page 106: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 7 way

How to apply map / filter / reduce

to List<Person> ?

Page 107: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 7 way

How to apply map / filter / reduce

to List<Person> ?

The legal way is to iterate over the elements

and apply the pattern

Page 108: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The JDK 7 way

How to apply map / filter / reduce

to List<Person> ?

The legal way is to iterate over the elements

and apply the pattern

One can create a helper method

Page 109: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Applying map to a List

With a helper method, JDK 7

List<Person> persons = new ArrayList<>() ; List<Integer> ages = // ages is a new list Lists.map( persons, new Mapper<Person, Integer>() { public Integer map(Person p) { return p.getAge() ; } } ) ;

Page 110: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Applying map to a List

With a helper method, JDK 8 & lambdas

List<Person> persons = new ArrayList<>() ; List<Integer> ages = Lists.map( persons, person -> person.getAge() ) ;

Page 111: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Applying map to a List

With a helper method, JDK 8 & lambdas

List<Person> persons = new ArrayList<>() ; List<Integer> ages = Lists.map( persons, Person::getAge ) ;

Page 112: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Applying map to a List

Caveats : beware the generics : what about managers ?

We want that to compile !

List<Manager> managers = new ArrayList<>() ; List<Integer> ages = Lists.map( managers, person -> person.getAge() ) ;

Page 113: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Applying map to a List

Caveats : beware the generics

// in Lists public static <T, V> List<V> map( List<? extends T> list, Mapper<T, V> mapper) { List<V> result = new ArrayList<>() ; for (T t : list) { V v = mapper.map(t) ; result.add(v) ; } return result ; }

Page 114: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

The map / filter / reduce pattern would look like this

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 115: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

The map / filter / reduce pattern would look like this

The idea is to push lambdas to the API, and let it apply

them on its content

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 116: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

The map / filter / reduce pattern would look like this

Pro : the API can be optimized

without touching the code : great !

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 117: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

The map / filter / reduce pattern would look like this

Pro : the API can be optimized

without touching the code

Cons …

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 118: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

1) Suppose persons is a really BIG list

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 119: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

1) Suppose persons is a really BIG list

2 duplications : ages & agesGT20

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 120: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

1) Suppose persons is a really BIG list

2 duplications : ages & agesGT20

What do we do with them ? Send them to the GC

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 121: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

2) Suppose the algorithms to compute the map / filter /

reduce are optimal

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 122: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

2) Suppose the algorithms to compute the map / filter /

reduce are optimal

… but I need to go even faster !

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 123: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

2) Suppose the algorithms to compute the map / filter /

reduce are optimal

Only solution : go parallel !

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 124: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

2) Suppose we want to go parallel

ages & agesGT20 would better be concurrent aware !

Because they will be accessed concurrently

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 125: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

3) Suppose we have a allMatch() reducer

allMatch is true if all the names are shorter than 20 chars

let’s see a possible implementation of allMatch()

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<String> names = Lists.map(persons, p -> p.getName()) ; boolean allMatch = Lists.allMatch(names, n -> n.length() < 20) ;

Page 126: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How could one write allMatch ?

Here is a basic implementation of allMatch

public static <T> boolean allMatch( List<? extends T> list, Filter<T> filter) { for (T t : list) { if (!filter.filter(t)) { return false ; } } return true ; }

Page 127: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How could one write allMatch ?

Here is a basic implementation of allMatch

public static <T> boolean allMatch( List<? extends T> list, Filter<T> filter) { for (T t : list) { if (!filter.filter(t)) { return false ; } } return true ; }

No need to iterate

over the whole list

Page 128: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How could one write allMatch ?

Here is a basic implementation of allMatch

public static <T> boolean allMatch( List<? extends T> list, Filter<T> filter) { for (T t : list) { if (!filter.filter(t)) { return false ; } } return true ; }

But…

Page 129: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

When we apply the allMatch() reducer…

… the list names has already been evaluated !

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<String> names = Lists.map(persons, p -> p.getName()) ; boolean allMatch = Lists.allMatch(names, n.length() < 20) ;

Page 130: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

When we apply the allMatch() reducer…

… the list names has already been evaluated !

We lost a big opportunity for optimization !

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<String> names = Lists.map(persons, p -> p.getName()) ; boolean allMatch = Lists.allMatch(names, n.length() < 20) ;

Page 131: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Putting things together

When we apply the allMatch() reducer…

… we should have wait to apply the filter

A good way to do that : apply the filter step lazily !

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<String> names = Lists.map(persons, p -> p.getName()) ; boolean allMatch = Lists.allMatch(names, n.length() < 20) ;

Page 132: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Pro : 1

Cons : 3 (at least)

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Page 133: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;

Conclusion

Pro : 1

Cons : 3 (at least)

Page 134: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

And the same goes for this one

// applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = persons.map(p -> p.getAge()) ; List<Integer> agesGT20 = ages.filter(a -> a > 20) ; int sum = agesGT20.reduce(ages, (i1, i2) -> i1 + i2) ;

Page 135: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

What about « in place » operations ?

Not possible for the map step, because the type of the list

changes

Could be evaluated for the filter, with concurrency issues

Doesnt make sense for the reduction

Page 136: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion (again)

We need a new concept to handle BIG lists efficiently

Page 137: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion (again)

We need a new concept to handle BIG lists efficiently

The Collection framework is not the right one…

Page 138: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion (again)

We need a new concept to handle BIG lists efficiently

The Collection framework is not the right one

We need something else !

Page 139: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

So what pattern

to choose ?

Page 140: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Introduction

Putting map / filter / reduce methods on Collection

would have led to :

And even if it doesnt lead to viable patterns,

it is still a pleasant way of writing things

// map / filter / reduce pattern on collections int sum = persons .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;

Page 141: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Introduction

Let’s keep the same kind of pattern and add a stream()

// map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;

Page 142: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Introduction

Collection.stream() returns a Stream : new interface

New interface = our hands are free !

// map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;

Page 143: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

New Collection interface

So we need a new method on Collection

public interface Collection<E> { // our good old methods Stream<E> stream() ; }

Page 144: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

New Collection interface

Problem : ArrayList doesnt compile anymore…

Something has to be done !

public interface Collection<E> { // our good old methods Stream<E> stream() ; }

Page 145: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Interfaces

Problem : ArrayList doesnt compile anymore…

Something has to be done !

Something that does not need to change or recompile all

the existing implementations of Collection

Page 146: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions ?

#DV13LBDS

Page 147: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

New interfaces

Page 148: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java 8 interfaces

Problem : ArrayList doesnt compile anymore…

Something has to be done !

Something that does not need to change or recompile all

the existing implementations of Collection

Problem : how to add methods to an interface, without

changing any of the implementations ?

Page 149: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java 8 interfaces

Problem : how to add methods to an interface, without

changing any of the implementations ?

Solution : change the way interfaces work in Java

Page 150: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java 8 interfaces

ArrayList needs to know the implementation of stream()…

public interface Collection<E> { // our good old methods Stream<E> stream() ; }

Page 151: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java 8 interfaces

Let’s put it in the interface !

public interface Collection<E> { // our good old methods default Stream<E> stream() { return ... ; } }

Page 152: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java 8 interfaces

Let’s introduce default methods in Java

Default methods are about interface evolution

Allows the extension of old interfaces

public interface Collection<E> { // our good old methods default Stream<E> stream() { return ... ; } }

Page 153: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Does it bring multiple inheritance to Java ?

Page 154: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Does it bring multiple inheritance to Java ?

Yes ! But we already have it

Page 155: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Does it bring multiple inheritance to Java ?

Yes ! But we already have it

public class String implements Serializable, Comparable<String>, CharSequence { // ... }

Page 156: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

What we have so far is multiple inheritance of type

Page 157: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

What we have so far is multiple inheritance of type

What we get in Java 8 is multiple inheritance of behavior

Page 158: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

What we have so far is multiple inheritance of type

What we get in Java 8 is multiple inheritance of behavior

What we dont have is multiple inheritance of state

Page 159: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

What we have so far is multiple inheritance of type

What we get in Java 8 is multiple inheritance of behavior

What we dont have is multiple inheritance of state

… and this is where the trouble is !

Page 160: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Will we have conflicts ?

Page 161: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Will we have conflicts ?

Oooh yes…

Page 162: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Will we have conflicts ?

Oooh yes…

So we need rules to handle them

Page 163: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

public class C implements A, B { // ... }

Page 164: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

public class C implements A, B { // ... }

public interface A { default String a() { ... } }

public interface B { default String a() { ... } }

Page 165: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Example #0

Class wins !

No default if an implementation is provided

public class C implements A, B { public String a() { ... } }

public interface A { default String a() { ... } }

public interface B { default String a() { ... } }

Page 166: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Example #1

public class C implements A, B { // ... }

public interface A { default String a() { ... } }

public interface B { default String a() { ... } }

Page 167: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Example #1

Compile time error :

class C inherits unrelated defaults for a() from types A and B

public class C implements A, B { // ... }

public interface A { default String a() { ... } }

public interface B { default String a() { ... } }

Page 168: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Example #2

A is more specific than B : A.a() is chosen

public class C implements A, B { // ... }

public interface A extends B { default String a() { ... } }

public interface B { default String a() { ... } }

Page 169: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Example #2

public class C implements A { // ... }

public interface A extends B { default String a() { ... } }

public interface B { default String a() { ... } }

public class D extends C implements B { // ... }

Page 170: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Example #2

A is still more specific than B : A.a() is chosen

public class C implements A { // ... }

public interface A extends B { default String a() { ... } }

public interface B { default String a() { ... } }

public class D extends C implements B { // ... }

Page 171: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Default methods

Back to example #1

We can also make an explicit call

public interface A { default String a() { ... } }

public interface B { default String a() { ... } }

public class C implements A, B { public String a() { return B.super.a() ; } }

Page 172: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

3 simple rules

To handle the conflict of multiple inheritance of behavior

Page 173: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

3 simple rules

To handle the conflict of multiple inheritance of behavior

1) Class wins !

Page 174: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

3 simple rules

To handle the conflict of multiple inheritance of behavior

1) Class wins !

2) More specific interfaces wins over less specific

Page 175: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

3 simple rules

To handle the conflict of multiple inheritance of behavior

1) Class wins !

2) More specific interfaces wins over less specific

3) In fact there’s no rule #3

Page 176: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

An example

Everybody who writes an implementation of Iterator

writes this :

public class MyIterator implements Iterator<E> { // some critical business code public void remove() { throw new UnsupportedOperationException("You shouldnt do that") ; } ; }

Page 177: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

An example

Thanks to Java 8 :

No silly implementation of remove() anymore !

public interface Iterator<E> { default void remove() { throw new UnsupportedOperationException("remove") ; } ; }

Page 178: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java 8 interfaces

So the concept of « interface » changed in Java 8

public class HelloWorld { // souvenir souvenir public static void main(String[] args) { System.out.println("Hello world!") ; } ; }

Page 179: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java 8 interfaces

So the concept of « interface » changed in Java 8

I mean, really

public interface HelloWorld { // souvenir souvenir public static void main(String[] args) { System.out.println("Hello world!") ; } ; }

Page 180: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Java 8 interfaces

1) Default methods, multiple behavior inheritance

Rules to handle conflicts, solved at compile time

2) Static methods in interfaces

Will bring new patterns and new ways to write APIs

Page 181: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Where are we ?

1) We have a new syntax

2) We have a new pattern to implement

3) We have new interfaces to keep the backward

compatibily

Page 182: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Where are we going to ?

1) The Stream API

2) Reductions

3) Performances

4) Collectors

But for now…

Page 183: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 184: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Stream API

Page 185: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

What is a Stream

From a technical point of view : a typed interface

« a stream of String »

Page 186: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

What is a Stream

From a technical point of view : a typed interface

Other classes for primitive types :

« a stream of String »

IntStream, LongStream, DoubleStream

Page 187: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

It’s a new notion

It‘ looks like a collection, but…

- It is built on a « source », that can be a collection

- No data needs to be provided at build time

- No limit on what the source can produce

Page 188: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

It’s a new notion

A stream can be built on :

- A collection or an array

- An iterator

- An I/O source

Some of those can be « infinite »

Page 189: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

It’s a new notion

1) A stream doesnt hold any data

It’s just an object on which one can declare operations

Streams are about « specifying computations »

Page 190: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

It’s a new notion

1) A stream doesnt hold any data

2) A stream cant modify its source

Consequence : it can use parallel processing

Page 191: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

It’s a new notion

1) A stream doesnt hold any data

2) A stream cant modify its source

3) A source can be infinite

So we need a way to guarantee that computations

will be conducted in finite time

Page 192: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

It’s a new notion

1) A stream doesnt hold any data

2) A stream cant modify its source

3) A source can be infinite

4) A stream works lazily

Then optimizations can be made among the different

operations

We need a way / convention to trigger the computations

Page 193: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is a Stream the same as a collection ?

Answer is no

Page 194: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is a Stream the same as a collection ?

Answer is no

A Collection provides means to access the elements one

by one

Page 195: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is a Stream the same as a collection ?

Answer is no

A Collection provides means to access the elements one

by one

A Stream does not

Page 196: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is a Stream the same as a collection ?

Answer is no

A Collection does not provide any mean to process its

elements with lambdas

Page 197: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is a Stream the same as a collection ?

Answer is no

A Collection does not provide any mean to process its

elements with lambdas

A Stream does

Page 198: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How can we build a stream ?

Many ways…

1) From a collection : method Collection.stream

Collection<String> collection = ... ; Stream<String> stream = collection.stream() ;

Page 199: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How can we build a stream ?

Many ways…

1) From a collection : method Collection.stream

2) From an array : Arrays.stream(Object [])

Stream<String> stream2 = Arrays.stream(new String [] {"one", "two", "three"}) ;

Page 200: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How can we build a stream ?

Many ways…

1) From a collection : method Collection.stream

2) From an array : Arrays.stream(Object [])

3) From factory methods in Stream, IntStream, …

Stream<String> stream1 = Stream.of("one", "two", "three") ;

Page 201: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How can we build a stream ?

Some last patterns

Stream.empty() ; // returns an empty Stream Stream.of(T t) ; // a stream with a single element Stream.generate(Supplier<T> s) ; Stream.iterate(T seed, UnaryOperator<T> f) ;

Page 202: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How can we build a stream ?

Other ways scattered in the JDK

string.chars() ; // returns a IntStream lineNumberReader.lines() ; // returns a Stream<String> random.ints() ; // return a IntStream

Page 203: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How can we build a stream ?

Factory methods : a closer look

A stream builder is a consumer

- one sends it elements, that are accepted

- it builds back a stream on the build() call with the

accepted elemts

- it has a life cycle

Stream.build() ; // returns a Stream.Builder

Page 204: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How can we build a stream ?

And as a last resort : StreamSupport + Spliterator

« This class is mostly for library writers

presenting stream views of data structures;

most static stream methods intended for end

users are in the various Stream classes »

Page 205: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A 1st example

Back to our map / filter / reduce example

// map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;

Build a stream

on a List

Page 206: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A 1st example

Back to our map / filter / reduce example

// map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;

Declare

operations

Page 207: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A 1st example

Back to our map / filter / reduce example

// map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;

Triggers the

computation

Page 208: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A 1st example

Back to our map / filter / reduce example

// map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;

Default value, in case the

stream is empty

Page 209: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Two types of operations

One can declare operations on a Stream

Two types of operations :

1) Intermediate operations : declarations, processed lazily

ex : map, filter

Page 210: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Two types of operations

One can declare operations on a Stream

Two types of operations :

1) Intermediate operations : declarations, processed lazily

ex : map, filter

2) Terminal operations : trigger the computations

ex : reduce

Page 211: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

State of a stream

The implementation of Stream has a state :

- SIZED : the number of elements is known

- ORDERED : the order matters (List)

- DISTINCT : all elements are unique (Set)

- SORTED : all elements have been sorted (SortedSet)

Page 212: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

State of a stream

Some operations change that :

- filtering removes the SIZED

- mapping removes DISTINCT and SORTED

Page 213: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

State of a stream

And it allows nice optimizations !

- a HashSet cant have doubles so…

Page 214: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

State of a stream

And it allows nice optimizations !

- a HashSet cant have doubles so…

- distinct() is NOPed on a stream built on a HashSet

Page 215: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

State of a stream

And it allows nice optimizations !

- a HashSet cant have doubles so…

- distinct() is NOPed on a stream built on a HashSet

- A TreeSet is sorted so…

Page 216: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

State of a stream

And it allows nice optimizations !

- a HashSet cant have doubles so…

- distinct() is NOPed on a stream built on a HashSet

- A TreeSet is sorted so…

- sorted() is NOPed on a stream built on a TreeSet

Page 217: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A 2nd example

Sorting a list of String

List<String> strings = new ArrayList<>() ; // populate the list with strings // then somewhere else in the code : List<String> result = strings.stream() .sorted() .collect(Collector.toList()) ;

Page 218: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A 2nd example

Sorting a list of String

// then some smart guy changes the implementation SortedSet<String> strings = new TreeSet<>() ; // populate the list with strings // then somewhere else in the code : List<String> result = strings.stream() .sorted() .collect(Collector.toList()) ;

Page 219: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A 2nd example

Sorting a list of String

In this case, no sorting is required, and executed !

// then some smart guy changes the implementation SortedSet<String> strings = new TreeSet<>() ; // populate the list with strings // then somewhere else in the code : List<String> result = strings.stream() .sorted() .collect(Collector.toList()) ;

Page 220: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Stateless / statefull operations

Stateless / statefull operations

Some operations are stateless :

It means that they dont need more information than the

one held by their parameters

persons.stream().map(p -> p.getAge()) ;

Page 221: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Stateless / statefull operations

Stateless / statefull operations

Some operations are stateless :

Some need to retain information :

persons.stream().map(p -> p.getAge()) ;

stream.limit(10_000_000) ; // select the 10M first elements

Page 222: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

Random rand = new Random() ; String [] strings = new String[10_000_000] ; for (int i = 0 ; i < strings.length ; i++) { strings[i] = Long.toHexString(rand.nextLong()) ; }

Page 223: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

Soooo Java 7…

Random rand = new Random() ; String [] strings = new String[10_000_000] ; for (int i = 0 ; i < strings.length ; i++) { strings[i] = Long.toHexString(rand.nextLong()) ; }

Page 224: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

Better ?

Random rand = new Random() ; Stream<String> stream = Stream.generate( () -> Long.toHexString(rand.nextLong()) ) ;

Page 225: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

Better !

// Random rand = new Random() ; Stream<String> stream = Stream.generate( () -> Long.toHexString(ThreadLocalRandom.current().nextLong()) ) ;

Page 226: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

// other way Stream<String> stream = ThreadLocalRandom .current() .longs() // returns a LongStream .mapToObj(l -> Long.toHexString(l)) ;

Page 227: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

// other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) ;

Page 228: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

// other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) .limit(10_000_000) .sorted() ;

T = 4 ms

Page 229: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

// other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) .limit(10_000_000) .sorted() ; Object [] sorted = stream.toArray() ;

Page 230: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

// other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) .limit(10_000_000) .sorted() ; Object [] sorted = stream.toArray() ;

T = 14 s

Page 231: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Example

Let’s sort an array of String

// other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) .limit(10_000_000) .sorted() ; Object [] sorted = stream.toArray() ;

T = 14 s

Intermediate calls !

Page 232: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

More on stream operations

1) There are intermediate and terminal operations

2) A stream is processed on a terminal operation call

Page 233: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

More on stream operations

1) There are intermediate and terminal operations

2) A stream is processed on a terminal operation call

3) Only one terminal operation is allowed

4) It cannot be processed again

If needed another stream should be built on the source

Page 234: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Parallel Streams

Page 235: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Optimization

The first optimization (well, laziness was first !) we need is

parallelism

The fork / join enable parallel programming since JDK 7

But writing tasks is hard and does not always lead to better

performances

Page 236: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Optimization

The first optimization (well, laziness was first !) we need is

parallelism

The fork / join enable parallel programming since JDK 7

But writing tasks is hard and does not always lead to better

performances

Using the parallel stream API is much more secure

Page 237: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

How to build a parallel stream ?

Two patterns

1) Call parallelStream() instead of stream()

2) Call parallel() on an existing stream

Stream<String> s = strings.parallelStream() ;

Stream<String> s = strings.stream().parallel() ;

Page 238: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Can we decide the # of cores ?

Answer is no

Page 239: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Can we decide the # of cores ?

Answer is no

But… do we really need it ?

Page 240: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Well… yes !

Page 241: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Well… yes !

… and no

Page 242: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Example 1 :

« returns the 10M first elements of the source »

persons.stream().limit(10_000_000) ;

Page 243: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Example 1 :

« returns the 10M first elements of the source »

persons.parallelStream().limit(10_000_000) ;

Page 244: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Example 1 :

« returns the 10M first elements of the source »

But how can I track the first 10M of the source on several

cores of my CPU ?

persons.parallelStream().limit(10_000_000) ;

Page 245: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Example 1 : performances

Code 1

List<Long> list = new ArrayList<>(10_000_100) ; for (int i = 0 ; i < 10_000_000 ; i++) { list1.add(ThreadLocalRandom.current().nextLong()) ; }

Page 246: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Example 1 : performances

Code 2

Stream<Long> stream = Stream.generate(() -> ThreadLocalRandom.current().nextLong()) ; List<Long> list1 = stream.limit(10_000_000).collect(Collectors.toList()) ;

Page 247: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Example 1 : performances

Code 3

Stream<Long> stream = ThreadLocalRandom.current().longs(10_000_000).mapToObj(Long::new) ; List<Long> list = stream.collect(Collectors.toList()) ;

Page 248: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Example 1 : performances

Serial Parallel

Code 1 (for) 270 ms

Code 2 (limit) 310 ms

Code 3 (longs) 250 ms

Page 249: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Example 1 : performances

Serial Parallel

Code 1 (for) 270 ms

Code 2 (limit) 310 ms 500 ms

Code 3 (longs) 250 ms 320 ms

Page 250: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Is parallelism really that simple ?

Example 2 :

« returns a stream with all the elements of the first stream

followed by all the elements of the second stream »

Stream s3 = Stream.concat(stream1, stream2) ;

Page 251: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Parallelism

Parallelism implies overhead most of the time

Badly configured parallel operations can lead to unneeded

computations that will slow down the overall process

Unnecessary ordering of a stream will lead to performance

hits

Page 252: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Back to our sorting example

Parallel version

Stream<String> stream = ... ; // created before the test Object [] sorted = stream.parallel() .sorted() // or not .toArray() ;

Page 253: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Sorting performances

In fact it’s not that simple

# Serial Parallel Ratio Ratio n.log(n)

10 33 ms 32 ms

100 1 ms 1 ms

1K 2 ms 1 ms

10K 5 ms 7 ms

100K 65 ms 49 ms

1M 540 ms 153 ms

10M 9,7 s 2,2 s

20M 19,1 s 4,78 s

30M 31,0 s 8,13 s

Page 254: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Sorting performances

In fact it’s not that simple

# Serial Parallel Ratio Ratio n.log(n)

10 33 ms 32 ms 1

100 1 ms 1 ms 1

1K 2 ms 1 ms 2

10K 5 ms 7 ms 0,7

100K 65 ms 49 ms 1,3

1M 540 ms 153 ms 3,5

10M 9,7 s 2,2 s 4,4

20M 19,1 s 4,78 s 4,0

30M 31,0 s 8,13 s 3,8

Page 255: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Sorting performances

In fact it’s not that simple

# Serial Parallel Ratio Ratio n.log(n)

10 33 ms 32 ms 1 1

100 1 ms 1 ms 1 664

1K 2 ms 1 ms 2 4982

10K 5 ms 7 ms 0,7 26,6K

100K 65 ms 49 ms 1,3 25,6K

1M 540 ms 153 ms 3,5 36,9K

10M 9,7 s 2,2 s 4,4 23,9K

20M 19,1 s 4,78 s 4,0 25,3K

30M 31,0 s 8,13 s 3,8 24,1K

Page 256: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions ?

#DV13LBDS

Page 257: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Reductions

Page 258: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

What is a reduction

2 kinds of reduction :

1) The reduction

« A reduction operation (also called a fold) takes a

sequence of input elements and combines them

into a single summary result by repeated

application of a combining operation »

Page 259: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

What is a reduction

2 kinds of reduction :

2) The mutable reduction

« A mutable reduction operation accumulates

input elements into a mutable result container,

such as a Collection or StringBuilder, as it

processes the elements in the stream »

Page 260: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A simple reduction

Sum of ages

// map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;

Page 261: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A simple reduction

It would be nice to be able to write :

But there’s no sum() on Stream<T>

What would be the sense of « adding persons » ?

// map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .sum() ;

Page 262: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A simple reduction

It would be nice to be able to write :

But there’s no sum() on Stream<T>

There’s one on IntStream !

// map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .sum() ;

Page 263: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A simple reduction

2nd version :

Value if persons is an empty list : 0

// map / filter / reduce pattern on collections int sum = persons.stream() .map(Person::getAge) .filter(a -> a > 20) .mapToInt(Integer::intValue) .sum() ;

Page 264: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A simple reduction

2nd version (even better) :

Value if persons is an empty list : 0

// map / filter / reduce pattern on collections int sum = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) // .mapToInt(Integer::intValue) .sum() ;

Page 265: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

A simple reduction

What about max() and min() ?

How can one chose a default value ?

// map / filter / reduce pattern on collections ....... = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) .max() ;

Page 266: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

The « default value » is a tricky notion

Page 267: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

The « default value » is a tricky notion

1) The « default value » is the reduction of the empty set

Page 268: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

The « default value » is a tricky notion

1) The « default value » is the reduction of the empty set

2) But it’s also the identity element for the reduction

Page 269: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 270: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 271: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 272: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 273: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 274: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 275: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 276: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 277: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

The « default value » is a tricky notion

1) The « default value » is the reduction of the empty set

2) But it’s also the identity element for the reduction

Page 278: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

Problem : max() and min() have no identity element

eg : an element e for which max(e, a) = a

Page 279: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

Problem : max() and min() have no identity element

eg : an element e for which max(e, a) = a

0 cant be, max(0, -1) is not -1…

−∞ is not an integer

Page 280: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

So what is the default value of max() and min() ?

Page 281: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

So what is the default value of max() and min() ?

Answer : there is no default value for max() and min()

Page 282: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

So what is the returned value of the max() reduction ?

// map / filter / reduce pattern on collections ....... = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) .max() ;

Page 283: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Problem with the default value

So what is the returned value of the max() reduction ?

If it’s int, then the default value will be 0…

// map / filter / reduce pattern on collections ....... = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) .max() ;

Page 284: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Optionals

Since there’s none, we need another notion

// map / filter / reduce pattern on collections OptionalInt optionalMax = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) .max() ;

« there might be no

result »

Page 285: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Optionals

What can I do with OptionalInt ?

1st pattern : test if it holds a value

OptionalInt optionalMax = ... ; int max ; if (optionalMax.isPresent()) { max = optionalMax.get() ; } else { max = ... ; // decide a « default value » }

Page 286: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Optionals

What can I do with OptionalInt ?

2nd pattern : read the held value, can get an exception

OptionalInt optionalMax = ... ; // throws NoSuchElementException if no held value int max = optionalMax.getAsInt() ;

Page 287: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Optionals

What can I do with OptionalInt ?

3rd pattern : read the held value, giving a default value

OptionalInt optionalMax = ... ; // get 0 if no held value int max = optionalMax.orElse(0) ;

Page 288: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Optionals

What can I do with OptionalInt ?

4th pattern : read the held value, or throw an exception

OptionalInt optionalMax = ... ; // exceptionSupplier will supply an exception, if no held value int max = optionalMax.orElseThrow(exceptionSupplier) ;

Page 289: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Available optionals

Optional<T>

OptionalInt, OptionalLong, OptionalDouble

Page 290: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Available reductions

On Stream<T> :

- reduce(), with different parameters

- count(), min(), max()

- anyMatch(), allMatch(), noneMatch()

- findFirst(), findAny()

- toArray()

- forEach(), forEachOrdered()

Page 291: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Available reductions

On IntStream, LongStream, DoubleStream :

- average()

- summaryStatistics()

Page 292: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Available reductions

SummaryStatistics is an object that holds :

- Count, Min, Max, Sum, Average

It’s a consumer, so it can be easily extended to compute

other statistics

Page 293: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Mutable reductions : example 1

Use of the helper class : Collectors

ArrayList<String> strings = stream .map(Object::toString) .collect(Collectors.toList()) ;

Page 294: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Mutable reductions : example 2

Concatenating strings with a helper

String names = persons .stream() .map(Person::getName) .collect(Collectors.joining()) ;

Page 295: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Mutable reductions

Common things :

- have a container : Collection or StringBuilder

- have a way to add an element to the container

- have a way to merge two containers (for parallelization)

Page 296: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Mutable reductions

The general form works with 3 objects :

- a supplier : supplies a new instance of the mutable result

container

Supplier<ArrayList<String>> supplier = () -> new ArrayList<String>() ;

Page 297: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Mutable reductions

The general form works with 3 objects :

- a supplier : supplies a new instance of the mutable result

container

- an accumulator : takes an partly filled container and

adds an element to it

BiConsumer<ArrayList<String>, ? super String> accumulator = (suppliedList, s) -> suppliedList.add(s) ;

Page 298: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Mutable reductions

The general form works with 3 objects :

- a supplier : supplies a new instance of the mutable result

container

- an accumulator : takes an partly filled container and

adds an element to it

- a combiner : takes two partly filled containers and

combines them

BiConsumer<ArrayList<String>, ArrayList<String>> combiner = (supplied1, supplied2) -> supplied1.addAll(supplied2) ;

Page 299: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Mutable reductions : example 1

Putting things together :

ArrayList<String> strings = stream .map(Object::toString) .collect( () -> new ArrayList<String>(), // the supplier (suppliedList, s) -> suppliedList.add(s), // the accumulator (supplied1, supplied2) -> supplied1.addAll(supplied2) // the combiner ) ;

Page 300: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Mutable reductions : example 1

Putting things together :

ArrayList<String> strings = stream .map(Object::toString) .collect( ArrayList::new, // the supplier ArrayList::add, // the accumulator ArrayList::addAll // the combiner ) ;

Page 301: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Collectors

Page 302: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collectors class

A rich toolbox (37 methods) for various types of reductions

- counting, minBy, maxBy

- summing, averaging, summarizing

- joining

- toList, toSet

And

- mapping, groupingBy, partionningBy

Page 303: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collectors class

Average, Sum, Count

persons .stream() .collect(Collectors.averagingDouble(Person::getAge)) ;

persons .stream() .collect(Collectors.counting()) ;

Page 304: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collectors class

Concatenating the names in a String

String names = persons .stream() .map(Person::getName) .collect(Collectors.joining(", ")) ;

Page 305: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collectors class

Accumulating in a List, Set

Set<Person> setOfPersons = persons .stream() .collect( Collectors.toSet()) ;

Page 306: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collectors class

Accumulating in a custom collection

TreeSet<Person> treeSetOfPersons = persons .stream() .collect( Collectors.toCollection(TreeSet::new)) ;

Page 307: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collectors class

Getting the max according to a comparator

Bonus : new API to build comparators

Optional<Person> optionalPerson = persons .stream() .collect( Collectors.maxBy( Comparator.comparing(Person::getAge)) ;

Page 308: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Building comparators

New API to build comparators in a declarative way

Comparator<Person> comp = Comparator.comparing(Person::getLastName) .thenComparing(Person::getFirstName) .thenComparing(Person:getAge) ;

Page 309: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collectors class : mapping

The mapping helper method takes 2 parameter :

- a function, that maps the elements of the stream

- a collector, called a « downstream », that is applied to

the mapped values

Page 310: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collectors class : mapping

Accumulating names in a set

Set<String> set = persons .stream() .collect( Collectors.mapping( Person::getLastName, Collectors.toSet())) ;

Page 311: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collectors class : mapping

Mapping the stream, then accumulating in a collection

TreeSet<String> set = persons .stream() .collect( Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ;

Page 312: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : groupingBy

« Grouping by » builds hash maps

- must explain how the keys are built

- by default the values are put in a list

- may specify a downstream (ie a collector)

Page 313: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : groupingBy

Grouping a list of persons by their age

Map<Integer, List<Person>> map = persons .stream() .collect( Collectors.groupingBy(Person::getAge)) ;

Page 314: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : groupingBy

Grouping a list of persons by their age

Map<Integer, Set<Person>> map = persons .stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.toSet() // the downstream ) ;

Page 315: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : groupingBy

Grouping a list of persons names by their age

Map<Integer, Set<String>> map = persons .stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.mapping( // Person::getLastName, // the downstream Collectors.toSet() // ) ) ;

Page 316: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : groupingBy

Grouping a list of persons names by their age

Map<Integer, TreeSet<String>> map = persons .stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new) ) ) ;

Page 317: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : groupingBy

Grouping a list of blah blah blah

TreeMap<Integer, TreeSet<String>> map = persons .stream() .collect( Collectors.groupingBy( Person::getAge, TreeMap::new, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new) ) ) ;

Page 318: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : groupingBy

Example : creating an age histogram

Gives the # of persons by age

Map<Integer, Long> map = persons .stream() .collect( Collectors.groupingBy(Person::getAge, Collectors.counting()) ) ;

Page 319: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : partionningBy

Creates a Map<Boolean, …> on a predicate

- the map has 2 keys : TRUE and FALSE

- may specify a downstream

Page 320: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : partionningBy

Creates a Map<Boolean, …> on a predicate

map.get(TRUE) returns the list people older than 20

Map<Boolean, List<Person>> map = persons .stream() .collect( Collectors.partitioningBy(p -> p.getAge() > 20) ) ;

Page 321: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : partionningBy

Can further process the list of persons

Map<Boolean, TreeSet<String>> map = persons .stream() .collect( Collectors.partitioningBy( p -> p.getAge() > 20, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ) ) ;

Page 322: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : partionningBy

Can further process the list of persons

Map<Boolean, TreeSet<String>> map = persons .stream() .collect( Collectors.partitioningBy( p -> p.getAge() > 20, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ) ) ;

Partition the persons

on age > 20

Page 323: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : partionningBy

Can further process the list of persons

Map<Boolean, TreeSet<String>> map = persons .stream() .collect( Collectors.partitioningBy( p -> p.getAge() > 20, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ) ) ;

Gather their names…

Page 324: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : partionningBy

Can further process the list of persons

Map<Boolean, TreeSet<String>> map = persons .stream() .collect( Collectors.partitioningBy( p -> p.getAge() > 20, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ) ) ;

… in TreeSets

Page 325: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : collectingAndThen

Collect data with a downstream

Then apply a function called a « finisher »

Useful for putting the result in a immutable collection

Page 326: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

The Collector API : collectingAndThen

In this case « Map::entrySet » is a finisher

Set<Map.Entry<Integer, List<Person>>> set = persons .stream() .collect( Collectors.collectingAndThen( Collectors.groupingBy( Person::getAge), // downstream, builds a map Map::entrySet // finisher, applied on the map ) ;

Page 327: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Questions ?

#DV13LBDS

Page 328: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Some real examples

Page 329: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

1st example

Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ;

Page 330: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

1st example

Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ;

A Stream of movies

Page 331: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

1st example

Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ;

Building a map

of year / # of movies

Page 332: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

1st example

Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ;

Then getting the

entry set

Page 333: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

1st example

Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ;

Then getting the

max by value

Page 334: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

1st example

Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ;

Returns the

year with the most

movies released

Page 335: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Some thoughts on parallel

Page 336: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Going parallel

To ways to do it :

- create a parallel stream up front

- call the parallel() method on a given stream, or

sequential() to go sequential

When a terminal operation is initiated, the operations are

executed in parallel or not, depending on the mode of the

stream

Page 337: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Things that will go wrong

Some operations, like findAny() dont give reproductible

results in parallel

Changing the source (which is forbidden) can lead to

unpredictable results even if the source is concurrent

aware

Page 338: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Things that will not go wrong, but…

The parallel processing of a stream has to be freed from

constraints

- ordering is costly, relaxing ordering may lead to better

performances

- Collecting must be concurrent aware

Page 339: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Page 340: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Why are lambdas introduced in Java 8 ?

Page 341: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Why are lambdas introduced in Java 8 ?

Because it’s in the mood !

Page 342: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 343: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Why are lambdas introduced in Java 8 ?

Because it’s in the mood !

Page 344: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Why are lambdas introduced in Java 8 ?

Because it’s in the mood !

Because it allows to write more compact code !

Page 345: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Compact code is better !

An example of compact code (in C)

#include "stdio.h" main() { int b=0,c=0,q=60,_=q;for(float i=-20,o,O=0,l=0,j,p;j=O*O,p=l*l, (!_--|(j+p>4)?fputc(b?q+(_/3):10,(i+=!b,p=j=O=l=0,c++,stdout)), _=q:l=2*O*l+i/20,O=j-p+o),b=c%q,c<2400;o=-2+b*.05) ; }

http://www.codeproject.com/Articles/2228/Obfuscating-your-Mandelbrot-code

Page 346: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Compact code is better !

An example of compact code (in C)

#include "stdio.h" main() { int b=0,c=0,q=60,_=q;for(float i=-20,o,O=0,l=0,j,p;j=O*O,p=l*l, (!_--|(j+p>4)?fputc(b?q+(_/3):10,(i+=!b,p=j=O=l=0,c++,stdout)), _=q:l=2*O*l+i/20,O=j-p+o),b=c%q,c<2400;o=-2+b*.05) ; }

http://www.codeproject.com/Articles/2228/Obfuscating-your-Mandelbrot-code

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++ ++ +++++++++++ +++++++++++++++++++++++++++++++++++ +++++++ ++++++++++++++++++++++++++++++++++++ +++++++ +++++++++++++++++++++++++++++++++++ ++++++++ ++++++++++++++++++++++++++++++++++ +++++++ +++++++++++++++++++++++++++++++++ +++++ +++++++++++++++++++++++++++++++++ ++++++ +++++++++++++++++++++++ + +++++ ++++++ +++++++++++++++++++++++ ++ ++++++ ++++++++++++++++++++++ + ++++++ ++++++++++++++++++++++ + ++++++ ++++++++++++++++++++ + + +++++++ ++++++ ++++++++ ++++++++++++++++++++ + + +++++++ ++++++++++++++++++++++ + ++++++ ++++++++++++++++++++++ + ++++++ +++++++++++++++++++++++ ++ ++++++ +++++++++++++++++++++++ + +++++ ++++++ +++++++++++++++++++++++++++++++++ ++++++ +++++++++++++++++++++++++++++++++ +++++ ++++++++++++++++++++++++++++++++++ +++++++ +++++++++++++++++++++++++++++++++++ ++++++++ ++++++++++++++++++++++++++++++++++++ +++++++ +++++++++++++++++++++++++++++++++++ +++++++ ++++++++++++++++++++++++++++++++++++ ++ +++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Page 347: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Why are lambdas introduced in Java 8 ?

Because it’s in the mood !

Because it allows to write more compact code !

Page 348: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Why are lambdas introduced in Java 8 ?

Because it brings new and efficient patterns,

that enable easy and safe parallelization,

- needed by modern applications

- needed by API writers

Page 349: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Java 8 is coming, it’s the biggest update in 15 years

Page 350: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Java 8 is coming, it’s the biggest update in 15 years

Moving to Java 8 means a lot of work for us developers !

- Self training

- Changing our habits

Page 351: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Java 8 is coming, it’s the biggest update in 15 years

Moving to Java 8 means a lot of work for us developers !

- Self training

- Changing our habits

- Convincing our bosses (sigh…)

Page 352: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Java 8 is coming, it’s the biggest update in 15 years

Download the develop preview version on Open JDK site

Release date : 18th march 2014 !

Page 353: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Java 8 is coming, it’s the biggest update in 15 years

Devoxx openning keynote

Brian Goetz : « Lamda a peek under the hood », Wed

12:00

Paul Sandoz : « In full flow : Java 8 lambdas in the

stream », Wed 14:00

Page 354: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Java 8 is coming, it’s the biggest update in 15 years

« Java is a blue collar language. It’s not PhD thesis

material but a language for a job » – James Gosling, 1997

Page 355: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Java 8 is coming, it’s the biggest update in 15 years

« Language features are not a goal unto themselves;

language features are enablers, encouraging or

discouraging certain styles and idioms » – Brian Goetz,

2013

Page 356: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Conclusion

Java 8 is coming, it’s the biggest update in 15 years

The good news is :

Java is still Java !

Page 357: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard

Page 358: Autumn collections : from iterable to lambdas, streams and collectors

#DV13LBDS @JosePaumard