Java 8 Streams & Collectors 
Patterns, performance, parallelization 
@JosePaumard
@JosePaumard
@JosePaumard 
Stream
@JosePaumard 
Stream Collectors
@JosePaumard 
Stream Collectors
@JosePaumard 
#J8Stream 
Code & slides 
1st part: slides 
-Stream 
-Operations 
-State 
-Reduction 
-Collectors 
2nd part:...
Questions ? 
#J8Stream 
@JosePaumard
@JosePaumard 
Stream
@JosePaumard 
#J8Stream 
What is a stream?
@JosePaumard 
#J8Stream 
What is a stream? 
Answer 1: a typed interface 
public interface Stream<T> extends BaseStream<T, ...
@JosePaumard 
#J8Stream 
What is a stream? 
Answer 1: a typed interface 
In fact: a new concept in the JDK 
public interfa...
@JosePaumard 
#J8Stream 
What is a stream? 
What can I do with it?
@JosePaumard 
#J8Stream 
What is a stream? 
What can I do with it? 
Answer: efficiently process high volumes of data, but ...
@JosePaumard 
#J8Stream 
What is a stream? 
What does efficiently mean?
@JosePaumard 
#J8Stream 
What is a stream? 
What does efficiently mean? 
Two things:
@JosePaumard 
#J8Stream 
What is a stream? 
What does efficiently mean? 
Two things: 
1)in parallel, to leverage multicore...
@JosePaumard 
#J8Stream 
What is a stream? 
What does efficiently mean? 
Two things: 
1)in parallel, to leverage multicore...
@JosePaumard 
#J8Stream 
What is a stream? 
Why cant a collection be a stream?
@JosePaumard 
#J8Stream 
What is a stream? 
Why cant a collection be a stream? 
In fact there are arguments for a Collecti...
@JosePaumard 
#J8Stream 
What is a stream? 
Why cant a collection be a stream? 
In fact there are arguments for a Collecti...
@JosePaumard 
#J8Stream 
What is a stream? 
Why cant a collection be a stream? 
In fact there are arguments for a Collecti...
@JosePaumard 
#J8Stream 
What is a stream? 
Why cant a collection be a stream? 
Two reasons: 
1)we want to be free to crea...
@JosePaumard 
#J8Stream 
What is a stream? 
Why cant a collection be a stream? 
Two reasons: 
1)we want to be free to crea...
@JosePaumard 
#J8Stream 
So: what is a Stream? 
Answers:
@JosePaumard 
#J8Stream 
So: what is a Stream? 
Answers: 
1)an object on which I can define operations
@JosePaumard 
#J8Stream 
So: what is a Stream? 
Answers: 
1)an object on which I can define operations 
2)that does not ho...
@JosePaumard 
#J8Stream 
So: what is a Stream? 
Answers: 
1)an object on which I can define operations 
2)that does not ho...
@JosePaumard 
#J8Stream 
So: what is a Stream? 
Answers: 
1)an object on which I can define operations 
2)that does not ho...
@JosePaumard 
#J8Stream 
So: what is a Stream? 
Answers: 
1)an object on which I can define operations 
2)that does not ho...
@JosePaumard 
#J8Stream 
How can I build a Stream? 
Many patterns!
@JosePaumard 
#J8Stream 
How can I build a Stream? 
Many patterns! 
Let us take one: 
List<Person> persons = ... ; 
Stream...
@JosePaumard 
#J8Stream 
Operations on a Stream 
Let us see a first operation: forEach() 
… that will display each person ...
@JosePaumard 
#J8Stream 
Operations on a Stream 
Let us see a first operation: forEach() 
… that will display each person ...
@JosePaumard 
#J8Stream 
Operations on a Stream 
Let us see a first operation: forEach() 
… that will display each person ...
@JosePaumard 
#J8Stream 
Operation: forEach() 
First operation: forEach() 
forEach(): takes a Consumer<T> as a parameter 
...
@JosePaumard 
#J8Stream 
Operation: forEach() 
First operation: forEach() 
forEach(): takes a Consumer<T> as a parameter 
...
@JosePaumard 
#J8Stream 
Functional interface 
Definition: 
an interface with only one abstract method
@JosePaumard 
#J8Stream 
Functional interface 
Definition: 
an interface with only one abstract method 
(methods from Obje...
@JosePaumard 
#J8Stream 
Functional interface 
Definition: 
an interface with only one abstract method 
(methods from Obje...
@JosePaumard 
#J8Stream 
Functional interface 
Definition: 
an interface with only one abstract method 
(methods from Obje...
@JosePaumard 
#J8Stream 
Functional interface 
Definition: 
an interface with only one abstract method 
(methods from Obje...
@JosePaumard 
#J8Stream 
In fact… 
Consumer is a bit more complex than that: 
@FunctionalInterface 
public interface Consu...
@JosePaumard 
#J8Stream 
In fact… 
What is a default method? 
@FunctionalInterface 
public interface Consumer<T> { 
void a...
@JosePaumard 
#J8Stream 
Default methods 
New concept in Java 8!
@JosePaumard 
#J8Stream 
Default methods 
New concept in Java 8! 
Added to allow the adding of methods in interfaces witho...
@JosePaumard 
#J8Stream 
Default methods 
New concept in Java 8! 
Added to allow the adding of methods in interfaces witho...
@JosePaumard 
#J8Stream 
Collection.stream() 
public interface Collection<E> { 
default Stream<E> stream() { 
return Strea...
@JosePaumard 
#J8Stream 
Collection.stream() 
public interface Collection<E> { 
default Stream<E> stream() { 
return Strea...
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
@FunctionalInterface 
public interface Consumer<T> { 
void accept...
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
List<String> list = new ArrayList<>() ; 
Consumer<String> c1 = s ...
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
List<String> list = new ArrayList<>() ; 
Consumer<String> c1 = li...
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
List<String> list = new ArrayList<>() ; 
Consumer<String> c1 = li...
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
Beware concurrency! 
List<String> result = new ArrayList<>() ; 
L...
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
Beware concurrency! 
List<String> result = new ArrayList<>() ; 
L...
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
Beware concurrency! 
List<String> result = new ArrayList<>() ; 
L...
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
Problem: forEach() returns void 
List<String> result = new ArrayL...
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
But I also have a peek() method 
That returns another Stream 
Lis...
@JosePaumard 
#J8Stream 
Back to Stream 
So far we saw: 
-forEach(Consumer) 
-peek(Consumer)
@JosePaumard 
#J8Stream 
Back to Stream 
3rd method: filter(Predicate)
@JosePaumard 
#J8Stream 
Method filter() 
3rd method: filter(Predicate) 
List<Person> list = ... ; 
Stream<Person> stream ...
@JosePaumard 
#J8Stream 
Method filter() 
3rd method: filter(Predicate) 
Predicate<Person> p = person -> person.getAge() >...
@JosePaumard 
#J8Stream 
Interface Predicate 
Another functional interface 
@FunctionalInterface public interface Predicat...
@JosePaumard 
#J8Stream 
Interface Predicate 
In fact Predicate looks like this: 
@FunctionalInterface 
public interface P...
@JosePaumard 
#J8Stream 
Interface Predicate 
default Predicate<T> and(Predicate<? super T> other) { 
return t -> test(t) ...
@JosePaumard 
#J8Stream 
Interface Predicate: patterns 
Predicate<Integer> p1 = i -> i > 20 ; 
Predicate<Integer> p2 = i -...
@JosePaumard 
#J8Stream 
Interface Predicate: patterns 
Predicate<Integer> p1 = i -> i > 20 ; 
Predicate<Integer> p2 = i -...
@JosePaumard 
#J8Stream 
Interface Predicate: patterns 
Predicate<Integer> p1 = i -> i > 20 ; 
Predicate<Integer> p2 = i -...
@JosePaumard 
#J8Stream 
Interface Predicate 
In fact Predicate looks like this (bis): 
@FunctionalInterface 
public inter...
@JosePaumard 
#J8Stream 
Interface Predicate 
static <T> Predicate<T> isEqual(Object o) { 
return t -> o.equals(t) ; 
}
@JosePaumard 
#J8Stream 
Interface Predicate 
In fact things are bit more complicated: 
static <T> Predicate<T> isEqual(Ob...
@JosePaumard 
#J8Stream 
Interface Predicate 
In fact things are bit more complicated: 
static <T> Predicate<T> isEqual(Ob...
@JosePaumard 
#J8Stream 
Interface Predicate 
We also have: 
@FunctionalInterface 
public interface BiPredicate<T, U> { 
b...
@JosePaumard 
#J8Stream 
Filtered Streams 
In this code: 
stream and filtered are different objects 
The filter() method r...
@JosePaumard 
#J8Stream 
Filtered Streams 
In this code: 
Question 1: what do we have in the filtered object? 
List<Person...
@JosePaumard 
#J8Stream 
Filtered Streams 
In this code: 
Question 1: what do we have in the filtered object? 
Answer: the...
@JosePaumard 
#J8Stream 
Filtered Streams 
In this code: 
Question 1: what do we have in the filtered object? 
Answer: the...
@JosePaumard 
#J8Stream 
Filtered Streams 
In this code: 
Question 1: what do we have in the filtered object? 
Didnt we sa...
@JosePaumard 
#J8Stream 
Filtered Streams 
In this code: 
Question 1: what do we have in the filtered object? 
Correct ans...
@JosePaumard 
#J8Stream 
Filtered Streams 
In this code: 
Question 2: what does this code do? 
List<Person> list = ... ; 
...
@JosePaumard 
#J8Stream 
Filtered Streams 
In this code: 
Question 2: what does this code do? 
Answer: nothing… 
List<Pers...
@JosePaumard 
#J8Stream 
Filtered Streams 
In this code: 
Question 2: what does this code do? 
Answer: nothing… 
This call...
@JosePaumard 
#J8Stream 
Filtered Streams 
The filter() call is a lazy call 
Generally speaking: 
A call to a method that ...
@JosePaumard 
#J8Stream 
Filtered Streams 
The filter() call is a lazy call 
Another way of saying it: 
An operation that ...
@JosePaumard 
#J8Stream 
Intermediate call 
Stating that a Stream does not hold any data 
creates the notion of intermedia...
@JosePaumard 
#J8Stream 
Intermediate call 
Stating that a Stream does not hold any data 
creates the notion of intermedia...
@JosePaumard 
#J8Stream 
Back to Consumer (bis) 
What happens in that code? 
List<String> result = new ArrayList<>() ; 
Li...
@JosePaumard 
#J8Stream 
Back to Consumer (bis) 
What happens in that code? 
Answer is: nothing! 
List<String> result = ne...
@JosePaumard 
#J8Stream 
Back to Consumer (bis) 
What happens in that code? 
1) nothing displayed 
2) result is empty 
Lis...
@JosePaumard 
#J8Stream 
What do we have so far? 
We saw: 
-forEach(Consumer) 
-peek(Consumer) 
-filter(Predicate)
@JosePaumard 
#J8Stream 
What do we have so far? 
We saw: 
-forEach(Consumer) 
-peek(Consumer) 
-filter(Predicate) 
The no...
@JosePaumard 
#J8Stream 
Let us carry on 
And see the mapping operation
@JosePaumard 
#J8Stream 
Mapping 
Mapping operation 
List<Person> list = ... ; 
Stream<Person> stream = list.stream() ; 
S...
@JosePaumard 
#J8Stream 
Mapping 
Mapping operation 
The map() method returns a Stream 
It is thus lazy / intermediate 
Li...
@JosePaumard 
#J8Stream 
Interface Function 
The map() method takes a Function: 
@FunctionalInterface 
public interface Fu...
@JosePaumard 
#J8Stream 
Interface Function 
Which in fact is: 
@FunctionalInterface 
public interface Function<T, R> { 
R...
@JosePaumard 
#J8Stream 
Interface Function 
Which in fact is: 
Beware the generics! 
@FunctionalInterface 
public interfa...
@JosePaumard 
#J8Stream 
Interface Function 
Which in fact is: 
@FunctionalInterface 
public interface Function<T, R> { 
R...
@JosePaumard 
#J8Stream 
Interface Function 
Which in fact is: 
@FunctionalInterface 
public interface Function<T, R> { 
R...
@JosePaumard 
#J8Stream 
Other functions 
There are special types of functions: 
@FunctionalInterface 
public interface Un...
@JosePaumard 
#J8Stream 
Other functions 
There are special types of functions: 
@FunctionalInterface 
public interface Bi...
@JosePaumard 
#J8Stream 
Other functions 
There are special types of functions: 
@FunctionalInterface 
public interface Bi...
@JosePaumard 
#J8Stream 
What do we have so far? 
We saw: 
-forEach(Consumer) 
-peek(Consumer) 
-filter(Predicate) 
-map(F...
@JosePaumard 
#J8Stream 
Let us carry on 
Method flatMap()
@JosePaumard 
#J8Stream 
Method flatMap() 
flatMap() = flattens a Stream 
The signature is: 
The passed function returns a...
@JosePaumard 
#J8Stream 
Method flatMap() 
Let us take an example: 
List<Movie> movies = ... ; // a movie has a set of Act...
@JosePaumard 
#J8Stream 
Method flatMap() 
Let us take an example: 
List<Movie> movies = ... ; // a movie has a set of Act...
@JosePaumard 
#J8Stream 
Method flatMap() 
Let us take an example: 
List<Movie> movies = ... ; // a movie has a set of Act...
@JosePaumard 
#J8Stream 
Method flatMap() 
Let us take an example: 
List<Movie> movies = ... ; // a movie has a set of Act...
@JosePaumard 
#J8Stream 
Method flatMap() 
flatMap() = flattens a Stream 
Signature: 
<R> Stream<R> flatMap(Function<T, St...
@JosePaumard 
#J8Stream 
Method flatMap() 
flatMap() = flattens a Stream 
Signature: 
Since it returns a Stream, it is a l...
@JosePaumard 
#J8Stream 
What do we have so far? 
We have 3 types of methods: 
-forEach(): consumes 
-peek(): consumes, an...
@JosePaumard 
#J8Stream 
What do we have so far? 
And what about reductions?
@JosePaumard 
#J8Stream 
Reduction 
Reduction method: 
List<Integer> ages = ... ; 
Stream<Integer> stream = ages.stream() ...
@JosePaumard 
#J8Stream 
Reduction 
Reduction method: 
Two things to stress out here 
List<Integer> ages = ... ; 
Stream<I...
@JosePaumard 
#J8Stream 
Reduction 
Reduction method: 
Two things to stress out here 
List<Integer> ages = ... ; 
Stream<I...
@JosePaumard 
#J8Stream 
Reduction 
Reduction method: 
0 is the « default value » of the reduction operation 
returned if ...
@JosePaumard 
#J8Stream 
Reduction 
Reduction method: 
0 is the « default value » of the reduction operation 
This « defau...
@JosePaumard 
#J8Stream 
Reduction 
Reduction method: 
0 is the « default value » of the reduction operation 
If it is not...
@JosePaumard 
#J8Stream 
Reduction 
Why? 
-This 0 is returned in case of an empty Stream 
-Red(0, p) is returned in case o...
@JosePaumard 
#J8Stream 
Reduction 
What is going to happen if the reduction operation has no identity value?
@JosePaumard 
#J8Stream 
Reduction 
What is going to happen if the reduction operation has no identity value? 
But of cour...
@JosePaumard 
#J8Stream 
Reduction 
Reduction method: 
The reduction operation should be associative 
List<Integer> ages =...
@JosePaumard 
#J8Stream 
Reduction 
Reduction method: 
The reduction operation should be associative 
If not, we will have...
@JosePaumard 
#J8Stream 
Reduction 
Associative, or not associative? 
red1 = (i1, i2) -> i1 + i2 ;
@JosePaumard 
#J8Stream 
Reduction 
Associative, or not associative? 
red1 = (i1, i2) -> i1 + i2 ;  
red2 = (i1, i2) -> i...
@JosePaumard 
#J8Stream 
Reduction 
Associative, or not associative? 
red1 = (i1, i2) -> i1 + i2 ;  
red2 = (i1, i2) -> i...
@JosePaumard 
#J8Stream 
Reduction 
Associative, or not associative? 
red1 = (i1, i2) -> i1 + i2 ;  
red2 = (i1, i2) -> i...
@JosePaumard 
#J8Stream 
Reduction 
Associative, or not associative? 
red1 = (i1, i2) -> i1 + i2 ;  
red2 = (i1, i2) -> i...
@JosePaumard 
#J8Stream 
Reduction 
Associative, or not associative? 
red1 = (i1, i2) -> i1 + i2 ;  
red2 = (i1, i2) -> i...
@JosePaumard 
#J8Stream 
Reduction 
Associative, or not associative? 
red1 = (i1, i2) -> i1 + i2 ;  
red2 = (i1, i2) -> i...
@JosePaumard 
#J8Stream 
Example of max 
Let us reduce with a max 
List<Integer> ages = ... ; 
Stream<Integer> stream = ag...
@JosePaumard 
#J8Stream 
Example of max 
Let us reduce with a max 
List<Integer> ages = ... ; 
Stream<Integer> stream = ag...
@JosePaumard 
#J8Stream 
Example of max 
Let us reduce with a max 
List<Integer> ages = ... ; 
Stream<Integer> stream = ag...
@JosePaumard 
#J8Stream 
Example of max 
Let us reduce with a max 
List<Integer> ages = ... ; 
Stream<Integer> stream = ag...
@JosePaumard 
#J8Stream 
Example of max 
Let us reduce with a max 
List<Integer> ages = ... ; 
Stream<Integer> stream = ag...
@JosePaumard 
#J8Stream 
Example of max 
Let us reduce with a max 
List<Integer> ages = ... ; 
Stream<Integer> stream = ag...
@JosePaumard 
#J8Stream 
Example of max 
The reduction with a max has a problem : why?
@JosePaumard 
#J8Stream 
Example of max 
The reduction with a max has a problem : why? 
Answer: the max reduction has no i...
@JosePaumard 
#J8Stream 
Example of max 
The reduction with a max has a problem : why? 
Answer: the max reduction has no i...
@JosePaumard 
#J8Stream 
Method max() 
Optional is the return type of the max() method 
List<Integer> ages = ... ; 
Stream...
@JosePaumard 
#J8Stream 
Optional 
An Optional is a wrapping type, that can be empty 
How can I use it? 
Optional<String> ...
@JosePaumard 
#J8Stream 
Optional 
An Optional is a wrapping type, that can be empty 
How can I use it? 
String s = opt.or...
@JosePaumard 
#J8Stream 
Optional 
An Optional is a wrapping type, that can be empty 
How can I use it? 
String s = opt.or...
@JosePaumard 
#J8Stream 
Optional can be built 
One can explicitly build optionals 
Optional<String> opt = Optional.<Strin...
@JosePaumard 
#J8Stream 
Optional: more patterns 
An Optional can be seen as a special Stream with zero or one element 
vo...
@JosePaumard 
#J8Stream 
Optional: more patterns 
An Optional can be seen as a special Stream with zero or one element 
vo...
@JosePaumard 
#J8Stream 
Optional: more patterns 
An Optional can be seen as a special Stream with zero or one element 
vo...
@JosePaumard 
#J8Stream 
Optional: more patterns 
An Optional can be seen as a special Stream with zero or one element 
vo...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
public class NewMath { 
public static Optional<Double> inv(Doubl...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
List<Double> doubles = Arrays.asList(-1d, 0d, 1d) ; 
List<Double...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
List<Double> doubles = Arrays.asList(-1d, 0d, 1d) ; 
List<Double...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
Function<Double, Optional<Double>> f = 
d -> NewMath.inv(d) // O...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
Function<Double, Optional<Double>> f = 
d -> NewMath.inv(d) // O...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
d -> NewMath.inv(d) // Optional<Double> 
.flatMap(NewMath::sqrt)...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
d -> NewMath.inv(d) // Optional<Double> 
.flatMap(NewMath::sqrt)...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
Function<Double, Stream<Double>> f = 
d -> NewMath.inv(d) // Opt...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
List<Double> doubles = Arrays.asList(-1d, 0d, 1d) ; 
List<Double...
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
List<Double> doubles = Arrays.asList(-1d, 0d, 1d) ; 
List<Double...
@JosePaumard 
#J8Stream 
Back on the reduce() method 
Two return types: 
List<Integer> ages = ... ; 
Stream<Integer> strea...
@JosePaumard 
#J8Stream 
Back on the reduce() method 
Two return types: 
List<Integer> ages = ... ; 
Stream<Integer> strea...
@JosePaumard 
#J8Stream 
More on the reduction 
A reduction never returns a Stream 
-max(), min() [optionals] 
-count() 
B...
@JosePaumard 
#J8Stream 
Note on the reduction 
A reduction never returns a Stream 
So it is not a lazy step / intermediat...
@JosePaumard 
#J8Stream 
Terminal operation 
Example 
List<Person> persons = ... ; 
... = 
persons.map(person -> person.ge...
@JosePaumard 
#J8Stream 
Terminal operation 
Example 
List<Person> persons = ... ; 
... = 
persons.map(Person::getAge) // ...
@JosePaumard 
#J8Stream 
Terminal operation 
Let us write a full map / filter / reduce 
List<Person> persons = ... ; 
Opti...
@JosePaumard 
#J8Stream 
Terminal operation 
Let us write a full map / filter / reduce 
List<Person> persons = ... ; 
bool...
@JosePaumard 
#J8Stream 
Terminal operation 
Let us write a full map / filter / reduce 
List<Person> persons = ... ; 
bool...
@JosePaumard 
#J8Stream 
Terminal operation 
Let us write a full map / filter / reduce 
Much more efficient to compute thi...
@JosePaumard 
#J8Stream 
What is a Stream? 
An object on which we can define operations on data 
No a priori limit on the ...
@JosePaumard 
#J8Stream 
What is a Stream? 
Pipeline approach: 
1)we define the operations 
2)we trigger the computations ...
@JosePaumard 
#J8Stream 
What is a Stream? 
And bytheway: 
We can only have one terminal operation for a Stream 
In case, ...
@JosePaumard 
#J8Stream 
How one can build a Stream? 
Let us have a look at the stream() default method 
List<Person> pers...
@JosePaumard 
#J8Stream 
How one can build a Stream? 
Let us have a look at the stream() default method 
// StreamSupport ...
@JosePaumard 
#J8Stream 
How one can build a Stream? 
The spliterator() is defined in ArrayList 
// ArrayList class @Overr...
@JosePaumard 
#J8Stream 
How one can build a Stream? 
The spliterator() is defined in ArrayList 
The Spliterator defines h...
@JosePaumard 
#J8Stream 
Spliterator 
Let us see the method we need to implement 
Consumes the next element, if it exists ...
@JosePaumard 
#J8Stream 
Spliterator 
Let us see the method we need to implement 
Consumes the next element, if it exists ...
@JosePaumard 
#J8Stream 
Spliterator 
Let us see the method we need to implement 
Used in parallel computations: tries to ...
@JosePaumard 
#J8Stream 
Spliterator 
Let us see the method we need to implement 
Returns an estimation of the size of thi...
@JosePaumard 
#J8Stream 
Spliterator 
And there are also default methods 
// Spliterator interface default void forEachRem...
@JosePaumard 
#J8Stream 
Spliterator 
And there is a last method: 
Implémentation for ArrayList 
// interface Spliterator ...
@JosePaumard 
#J8Stream 
Spliterator 
And there is a last method: 
Implémentation for HashSet 
// interface Spliterator 
i...
@JosePaumard 
#J8Stream 
Characteristics of a Stream 
Bits defined in the characteristics word 
Characteristic 
ORDERED 
T...
@JosePaumard 
#J8Stream 
Characteristics of a Stream 
Some operations will switch some bits 
Method 
Set to 0 
Set to 1 
f...
@JosePaumard 
#J8Stream 
Characteristics of a Stream 
Characteristics are taken into account when computing a result 
// H...
@JosePaumard 
#J8Stream 
Characteristics of a Stream 
Characteristics are taken into account when computing a result 
// S...
@JosePaumard 
#J8Stream 
Stream implementation 
Complex! 
Two parts: 
1)algorithms are in ReferencePipeline 
2)data access...
@JosePaumard 
#J8Stream 
A few words on Comparator 
We wrote: 
// Comparator interface 
Comparator cmp = Comparator.natura...
@JosePaumard 
#J8Stream 
A few words on Comparator 
We wrote: 
// Comparator interface Comparator cmp = Comparator.natural...
@JosePaumard 
#J8Stream 
A few words on Comparator 
// Comparators class 
enum NaturalOrderComparator 
implements Comparat...
@JosePaumard 
#J8Stream 
A few words on Comparator 
// Comparators class 
enum NaturalOrderComparator 
implements Comparat...
@JosePaumard 
#J8Stream 
A few words on Comparator 
// Comparators class 
enum NaturalOrderComparator 
implements Comparat...
@JosePaumard 
#J8Stream 
A few words on Comparator 
So we can write: 
// Comparator interface 
Comparator<Person> cmp = 
C...
@JosePaumard 
#J8Stream 
A few words on Comparator 
Method comparing() 
// Comparator interface 
public static 
<T, U> Com...
@JosePaumard 
#J8Stream 
A few words on Comparator 
Method comparing() 
// Comparator interface 
public static 
<T, U exte...
@JosePaumard 
#J8Stream 
A few words on Comparator 
Method comparing() 
// Comparator interface 
public static 
<T, U exte...
@JosePaumard 
#J8Stream 
A few words on Comparator 
Method thenComparing() 
// Comparator interface 
default 
<U> Comparat...
@JosePaumard 
#J8Stream 
A few words on Comparator 
Method thenComparing() 
// Comparator interface 
default 
<U extends C...
@JosePaumard 
#J8Stream 
A few words on Comparator 
Method thenComparing() 
// Comparator interface 
default Comparator<T>...
@JosePaumard 
#J8Stream 
What do we have so far? 
API Stream 
-intermediate operations 
-terminal operations 
-implementat...
@JosePaumard 
#J8Stream 
Stateless / stateful operations 
This code: 
… selects the 1000 first people of the list 
ArrayLi...
@JosePaumard 
#J8Stream 
Stateless / stateful operations 
This code: 
… selects the 1000 first people of the list 
This op...
@JosePaumard 
#J8Stream 
Stateless / stateful operations 
This code: 
ArrayList<Person> persons = ... ; 
List<String> name...
@JosePaumard 
#J8Stream 
Stateless / stateful operations 
This code: 
« the order of the names is the same as the order of...
@JosePaumard 
#J8Stream 
Stateless / stateful operations 
This code: 
« the order of the names is the same as the order of...
@JosePaumard 
#J8Stream 
Stateless / stateful operations 
This code: 
« the order of the names is the same as the order of...
@JosePaumard 
#J8Stream 
Wrap-up on Stream 
One can define operations on a Stream: 
-intermediate & terminal 
-stateless &...
@JosePaumard 
#J8Stream 
Stream & performance 
Two elements: 
-lazy processing, on one pass over the data 
-parallel proce...
@JosePaumard 
#J8Stream 
Stream & performance 
Two elements: 
-lazy processing, on one pass over the data 
-parallel proce...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again: 
ArrayList<Person> persons = ... ; 
persons.str...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again: 
ArrayList<Person> persons = ... ; 
persons.str...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again: 
ArrayList<Person> persons = ... ; 
persons.str...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again: 
ArrayList<Person> persons = ... ; 
persons.str...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again: 
ArrayList<Person> persons = ... ; 
persons.str...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again 
ArrayList<Person> persons = ... ; 
persons.stre...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again 
ArrayList<Person> persons = ... ; 
persons.stre...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again 
ArrayList<Person> persons = ... ; 
persons.stre...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again 
ArrayList<Person> persons = ... ; 
int sum = 
p...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again 
ArrayList<Person> persons = ... ; 
??? = 
perso...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again 
ArrayList<Person> persons = ... ; 
OptionalInt ...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again 
ArrayList<Person> persons = ... ; 
??? = 
perso...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again 
ArrayList<Person> persons = ... ; 
OptionalInt ...
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again 
sur l’exemple 
In one pass we have: count, sum,...
@JosePaumard 
#J8Stream 
Parallel streams 
How to build a parallel Stream? 
Built on top of fork / join 
ArrayList<Person>...
@JosePaumard 
#J8Stream 
Parallel streams 
By default, a parallel streams uses the default « fork join common pool », defi...
@JosePaumard 
#J8Stream 
Parallelism 
By default, a parallel streams uses the default « fork join common pool », defined a...
@JosePaumard 
#J8Stream 
Parallelism 
We can also decide the FJ pool for a given Stream 
List<Person> persons = ... ; 
For...
@JosePaumard 
#J8Stream 
Reduction 
A reduction can be seen as a SQL agregation (sum, min, max, avg, etc…)
@JosePaumard 
#J8Stream 
Reduction 
A reduction can be seen as a SQL agregation (sum, min, max, avg, etc…) 
But it can be ...
@JosePaumard 
#J8Stream 
Reduction 
Example: sum()
@JosePaumard 
#J8Stream 
Reduction 
Example: sum() 
The result is an integer, its initial value being 0
@JosePaumard 
#J8Stream 
Reduction 
Example: sum() 
The result is an integer, its initial value being 0 
Adding an element...
@JosePaumard 
#J8Stream 
Reduction 
Example: sum() 
The result is an integer, its initial value being 0 
Adding an element...
@JosePaumard 
#J8Stream 
Reduction 
So we have 3 operations:
@JosePaumard 
#J8Stream 
Reduction 
So we have 3 operations: 
-the definition of a container, which holds the result
@JosePaumard 
#J8Stream 
Reduction 
So we have 3 operations: 
-the definition of a container, which holds the result 
-add...
@JosePaumard 
#J8Stream 
Reduction 
So we have 3 operations: 
-the definition of a container, which holds the result 
-add...
@JosePaumard 
#J8Stream 
Reduction 
So we have 3 operations: 
-the definition of a container, which holds the result 
-add...
@JosePaumard 
#J8Stream 
Reduction 
So a reduction is based on 3 operations: 
-a constructor: Supplier 
-an accumulator: F...
@JosePaumard 
#J8Stream 
Reduction 
So a reduction is based on 3 operations: 
-a constructor: Supplier 
-an accumulator: F...
@JosePaumard 
#J8Stream 
Reduction 
So a reduction is based on 3 operations: 
-a constructor: Supplier 
-an accumulator: F...
@JosePaumard 
#J8Stream 
Reduction 
So a reduction is based on 3 operations: 
-a constructor: Supplier 
-an accumulator: F...
@JosePaumard 
#J8Stream 
Reduction 
So a reduction is based on 3 operations: 
-a constructor: Supplier 
-an accumulator: F...
@JosePaumard 
#J8Stream 
Reduction: implementation 
Example 1: reducing in a StringBuffer 
List<Person> persons = ... ; St...
@JosePaumard 
#J8Stream 
Reduction: collectors 
Example 1: using a Collectors 
List<Person> persons = ... ; String result ...
@JosePaumard 
#J8Stream 
Reduction: collectors 
Collecting in a String 
List<Person> persons = ... ; String result = perso...
@JosePaumard 
#J8Stream 
Reduction: collectors 
Collecting in a String 
List<Person> persons = ... ; String result = perso...
@JosePaumard 
#J8Stream 
Reduction 
Example 2: 
-a constructor: Supplier 
-an accumulator: Function 
-a combiner: Function...
@JosePaumard 
#J8Stream 
Reduction 
Example 2: 
-a constructor: Supplier 
-an accumulator: Function 
-a combiner: Function...
@JosePaumard 
#J8Stream 
Reduction: implementation 
Example 2: reduction in a List 
List<Person> persons = ... ; ArrayList...
@JosePaumard 
#J8Stream 
Reduction: collectors 
Example 2: reduction in a List 
List<Person> persons = ... ; List<String> ...
@JosePaumard 
#J8Stream 
Reduction: implementation 
Example 3: reduction in a Set 
List<Person> persons = ... ; HashSet<St...
@JosePaumard 
#J8Stream 
Reduction: collectors 
Example 3: reduction in a Set 
List<Person> persons = ... ; Set<String> re...
@JosePaumard 
#J8Stream 
Reduction: collectors 
Example 4: reduction in a given collection 
List<Person> persons = ... ; T...
@JosePaumard 
#J8Stream 
Collectors 
Collectors class: 33 static methods 
An amazing toolbox!
@JosePaumard 
#J8Stream 
Collectors: groupingBy 
HashMap: age / list of the people 
Map<Integer, List<Person>> result = 
p...
@JosePaumard 
#J8Stream 
Collectors: groupingBy 
HashMap: age / # of people 
Map<Integer, Long> result = 
persons.stream()...
@JosePaumard 
#J8Stream 
Collectors: groupingBy 
HashMap: age / list of the names 
Map<Integer, List<String>> result = 
pe...
@JosePaumard 
#J8Stream 
Collectors: groupingBy 
HashMap: age / names joined in a single String 
Map<Integer, String> resu...
@JosePaumard 
#J8Stream 
Collectors: groupingBy 
HashMap: age / names sorted alphabetically 
Map<Integer, TreeSet<String>>...
@JosePaumard 
#J8Stream 
Collectors: groupingBy 
HashMap: the same, sorted by age 
TreeMap<Integer, TreeSet<String>> resul...
@JosePaumard 
#J8Stream 
Wrap-up 
Stream + Collectors = 
New tools for data processing (map / filter / reduce) 
1)lazy exe...
@JosePaumard 
#J8Stream 
Wrap-up 
More to come: 
-use cases 
-live coding!
@JosePaumard 
Coffee time ! 
#Stream8
Java 8 Streams & Collectors 
Patterns, performance, parallelization 
@JosePaumard
Questions ? 
#J8Stream 
@JosePaumard
« movies and actors » 
https://github.com/JosePaumard/jdk8-lambda-tour 
http://introcs.cs.princeton.edu/java/data/
@JosePaumard 
#J8Stream 
Movies and actors 
File: « movies-mpaa.txt » 
With 14k movies from 1916 to 2004 
With: 
-the titl...
@JosePaumard 
#J8Stream 
Greatest release year 
1st question: which year saw the most movies?
@JosePaumard 
#J8Stream 
Greatest release year 
1st question: which year saw the most movies? 
1st step: we can build a ha...
@JosePaumard 
#J8Stream 
Greatest release year 
1st question: which year saw the most movies? 
1st step: we can build a ha...
@JosePaumard 
#J8Stream 
Greatest release year 
Live coding
@JosePaumard 
#J8Stream 
Greatest release year 
1st question: which year saw the most movies? 
Solution: map / reduce
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor?
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
Once again, we can build a hashmap: 
-the keys a...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
Let us build the set of all the actors 
Set<Acto...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream() .collect( ) .entrySet().stream()...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream() 
.collect( 
Collectors.toMap( 
)...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream() .collect( Collectors.toMap( acto...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream() 
.collect( 
Collectors.toMap( 
F...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream() .collect( Collectors.toMap( Func...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream().parallel() // T = 40s  
.collec...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream().parallel() // 170k .collect( Col...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
Set<Actor> actors = 
movies.stream() 
.flatMap(m...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
And in this stream, if an actor played in 2 movi...
@JosePaumard 
#J8Stream 
Most seen actor 
Live coding
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
Answer: Frank Welker
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
Answer: Frank Welker 
… and in fact he’s not rea...
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
Answer: Frank Welker
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen heard actor? 
Answer: Frank Welker
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year?
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year? 
So it is a hashmap in ...
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year? 
So it is a hashmap in ...
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year? 
movies.stream() 
.flat...
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year? 
movies.stream() .flatM...
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year? 
So it is a hashmap in ...
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year? 
We need 3 things to bu...
@JosePaumard 
#J8Stream 
Most seen actor in a year 
Live coding
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year?
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year? 
Answer: Phil Hawn, in ...
@JosePaumard 
#J8Stream 
Most seen actor in a year 
3rd question: most seen actor in a given year? 
Answer: Phil Hawn, in ...
« Shakespeare plays Scrabble » 
https://github.com/JosePaumard/jdk8-lambda-tour 
http://introcs.cs.princeton.edu/java/data/
@JosePaumard 
#J8Stream 
Scrabble 
Two files: 
-OSPD = official personnal Scrabble dictionary 
-The words used by Shakespe...
@JosePaumard 
#J8Stream 
Scrabble 
Two files: 
-OSPD = official personnal Scrabble dictionary 
-The words used by Shakespe...
@JosePaumard 
#J8Stream 
Scrabble: score of a word 
1st question: how to compute the score of a word 
H E L L O 4 1 1 1 1 ...
@JosePaumard 
#J8Stream 
Scrabble: score of a word 
1st question: how to compute the score of a word 
H E L L O 
4 1 1 1 1...
@JosePaumard 
#J8Stream 
Scrabble: score of a word 
1st question: how to compute the score of a word 
H E L L O // this is...
@JosePaumard 
#J8Stream 
Scrabble: score of a word 
1st question: how to compute the score of a word 
H E L L O // this is...
@JosePaumard 
#J8Stream 
Scrabble: score of a word 
1st question: how to compute the score of a word 
H E L L O // this is...
@JosePaumard 
#J8Stream 
Scrabble: score of a word 
Live coding
@JosePaumard 
#J8Stream 
Scrabble: score of a word 
1st question: how to compute the score of a word 
= map / reduce
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
2nd question: compute the best word of Shakespeare
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
2nd question: compute the best word of Shakespeare 
1)Histogram: ...
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
2nd question: compute the best word of Shakespeare 
1)Histogram: ...
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
2nd question: compute the best word of Shakespeare 
1)Histogram: ...
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
2nd question: compute the best word of Shakespeare 
1)Histogram: ...
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
Live coding
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
3rd question: filter out the wrong words 
We need to add a filter...
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
Live coding
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
3rd question: filter out the wrong words 
Solution: map / filter ...
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
Question: can one really write this word?
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
Question: can one really write this word? 
private static final i...
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
Answer: no… 
private static final int [] scrabbleENDistribution =...
@JosePaumard 
#J8Stream 
Filtering V2 
4th question: how to check if I have the available letters? 
private static final i...
@JosePaumard 
#J8Stream 
Filtering V2 
4th question: how to check if I have the available letters? 
1 
1 
2 
2 
1 
1 
need...
@JosePaumard 
#J8Stream 
Filtering V2 
4th question: how to check if I have the available letters? 
1 
1 
2 
2 
1 
1 
1 
4...
@JosePaumard 
#J8Stream 
Filtering V2 
4th question: how to check if I have the available letters? 
I need a allMatch() re...
@JosePaumard 
#J8Stream 
Filtering V2 
Live coding
@JosePaumard 
#J8Stream 
Filtering V2 
4th question: how to check if I have the available letters? 
Solution: map / filter...
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
5th question: and what about using blanks?
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
5th question: and what about using blanks? 
private static final int [] ...
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
5th question: and what about using blanks? 
private static final int [] ...
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
It has 2 impacts: 
-on the filtering of the words 
-on the computation o...
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
5th question: how to compute the score? 
1 
1 
2 
2 
1 
1
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
5th question: how to compute the score? 
1 
1 
2 
2 
1 
1 
1 
4 
9 
1 
6...
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
5th question: how to compute the score? 
1 
1 
2 
2 
1 
1 
1 
4 
9 
1 
6...
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
Live coding
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
5th question: how to compute the score? 
Solution: map / filter / reduce
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
6th question: how many blanks do we need? 
1 
1 
2 
2 
1 
1
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
6th question: how many blanks do we need? 
1 
1 
2 
2 
1 
1 
1 
4 
9 
1 ...
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
6th question: how many blanks do we need? 
1 
1 
2 
2 
1 
1 
1 
4 
9 
1 ...
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
6th question: how many blanks do we need? 
1 
1 
2 
2 
1 
1 
1 
4 
9 
1 ...
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
Live coding
@JosePaumard 
#J8Stream 
Use of a blank 
6th question: how many blanks do we need? 
Solution: map / reduce
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score?
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score?
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score?
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
6 solutio...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
6 solutio...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
So we nee...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
IntStream...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
Problem: ...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
Stream.of...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
Stream.of...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
What shou...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
… that ca...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: what about the Double letter score? 
… that ca...
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
Live coding
@JosePaumard 
#J8Stream 
Scrabble: and what about the board? 
7th question: can we take the Double letter score? 
Solution...
https://github.com/JosePaumard/jdk8-lambda-tour
@JosePaumard 
#J8Stream 
Conclusion 
Streams + Collectors = no need to use the Iterator pattern any more
@JosePaumard 
#J8Stream 
Conclusion 
Streams + Collectors = no need to use the Iterator pattern any more 
Combined with la...
@JosePaumard 
#J8Stream 
Conclusion 
Streams + Collectors = no need to use the Iterator pattern any more 
Combined with la...
@JosePaumard 
#J8Stream 
Conclusion 
Some books:
Thank you! 
@JosePaumard 
#Stream8
@JosePaumard 
#Stream8
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
Prochain SlideShare
Chargement dans…5
×

Java 8, Streams & Collectors, patterns, performances and parallelization

38 383 vues

Publié le

The slide deck of the talk I gave in Devoxx 2014

Publié dans : Formation
4 commentaires
43 j’aime
Statistiques
Remarques
Aucun téléchargement
Vues
Nombre de vues
38 383
Sur SlideShare
0
Issues des intégrations
0
Intégrations
25 750
Actions
Partages
0
Téléchargements
758
Commentaires
4
J’aime
43
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Java 8, Streams & Collectors, patterns, performances and parallelization

  1. 1. Java 8 Streams & Collectors Patterns, performance, parallelization @JosePaumard
  2. 2. @JosePaumard
  3. 3. @JosePaumard Stream
  4. 4. @JosePaumard Stream Collectors
  5. 5. @JosePaumard Stream Collectors
  6. 6. @JosePaumard #J8Stream Code & slides 1st part: slides -Stream -Operations -State -Reduction -Collectors 2nd part: live coding! -Movies & actors -Shakespeare
  7. 7. Questions ? #J8Stream @JosePaumard
  8. 8. @JosePaumard Stream
  9. 9. @JosePaumard #J8Stream What is a stream?
  10. 10. @JosePaumard #J8Stream What is a stream? Answer 1: a typed interface public interface Stream<T> extends BaseStream<T, Stream<T>> { // ... }
  11. 11. @JosePaumard #J8Stream What is a stream? Answer 1: a typed interface In fact: a new concept in the JDK public interface Stream<T> extends BaseStream<T, Stream<T>> { // ... }
  12. 12. @JosePaumard #J8Stream What is a stream? What can I do with it?
  13. 13. @JosePaumard #J8Stream What is a stream? What can I do with it? Answer: efficiently process high volumes of data, but also small ones
  14. 14. @JosePaumard #J8Stream What is a stream? What does efficiently mean?
  15. 15. @JosePaumard #J8Stream What is a stream? What does efficiently mean? Two things:
  16. 16. @JosePaumard #J8Stream What is a stream? What does efficiently mean? Two things: 1)in parallel, to leverage multicore CPU
  17. 17. @JosePaumard #J8Stream What is a stream? What does efficiently mean? Two things: 1)in parallel, to leverage multicore CPU 2)in pipeline, to avoid the computation of intermediate data structures
  18. 18. @JosePaumard #J8Stream What is a stream? Why cant a collection be a stream?
  19. 19. @JosePaumard #J8Stream What is a stream? Why cant a collection be a stream? In fact there are arguments for a Collection to be a Stream!
  20. 20. @JosePaumard #J8Stream What is a stream? Why cant a collection be a stream? In fact there are arguments for a Collection to be a Stream! 1)this is where my data is!
  21. 21. @JosePaumard #J8Stream What is a stream? Why cant a collection be a stream? In fact there are arguments for a Collection to be a Stream! 1)this is where my data is! 2)and I know the Collection API pretty well…
  22. 22. @JosePaumard #J8Stream What is a stream? Why cant a collection be a stream? Two reasons: 1)we want to be free to create new concepts
  23. 23. @JosePaumard #J8Stream What is a stream? Why cant a collection be a stream? Two reasons: 1)we want to be free to create new concepts 2)we dont want to add those concepts on well-known interfaces
  24. 24. @JosePaumard #J8Stream So: what is a Stream? Answers:
  25. 25. @JosePaumard #J8Stream So: what is a Stream? Answers: 1)an object on which I can define operations
  26. 26. @JosePaumard #J8Stream So: what is a Stream? Answers: 1)an object on which I can define operations 2)that does not hold any data
  27. 27. @JosePaumard #J8Stream So: what is a Stream? Answers: 1)an object on which I can define operations 2)that does not hold any data 3)that will not modify the data it processes
  28. 28. @JosePaumard #J8Stream So: what is a Stream? Answers: 1)an object on which I can define operations 2)that does not hold any data 3)that will not modify the data it processes 4)that will process data in « one pass »
  29. 29. @JosePaumard #J8Stream So: what is a Stream? Answers: 1)an object on which I can define operations 2)that does not hold any data 3)that will not modify the data it processes 4)that will process data in « one pass » 5)that is built on higly optimized algorithms, and that can work in parallel
  30. 30. @JosePaumard #J8Stream How can I build a Stream? Many patterns!
  31. 31. @JosePaumard #J8Stream How can I build a Stream? Many patterns! Let us take one: List<Person> persons = ... ; Stream<Person> stream = persons.stream() ;
  32. 32. @JosePaumard #J8Stream Operations on a Stream Let us see a first operation: forEach() … that will display each person List<Person> persons = ... ; Stream<Person> stream = persons.stream() ; stream.forEach(p -> System.out.println(p)) ;
  33. 33. @JosePaumard #J8Stream Operations on a Stream Let us see a first operation: forEach() … that will display each person List<Person> persons = ... ; Stream<Person> stream = persons.stream() ; stream.forEach(System.out::println) ;
  34. 34. @JosePaumard #J8Stream Operations on a Stream Let us see a first operation: forEach() … that will display each person List<Person> persons = ... ; Stream<Person> stream = persons.stream() ; stream.forEach(System.out::println) ; o -> System.out.println(o) ≡ System.out::println
  35. 35. @JosePaumard #J8Stream Operation: forEach() First operation: forEach() forEach(): takes a Consumer<T> as a parameter @FunctionalInterface public interface Consumer<T> { void accept(T t) ; }
  36. 36. @JosePaumard #J8Stream Operation: forEach() First operation: forEach() forEach(): takes a Consumer<T> as a parameter What is a functional interface? @FunctionalInterface public interface Consumer<T> { void accept(T t) ; }
  37. 37. @JosePaumard #J8Stream Functional interface Definition: an interface with only one abstract method
  38. 38. @JosePaumard #J8Stream Functional interface Definition: an interface with only one abstract method (methods from Object do not count)
  39. 39. @JosePaumard #J8Stream Functional interface Definition: an interface with only one abstract method (methods from Object do not count) (default & static methods do not count)
  40. 40. @JosePaumard #J8Stream Functional interface Definition: an interface with only one abstract method (methods from Object do not count) (default & static methods do not count) It « can » be annotated by @FunctionalInterface
  41. 41. @JosePaumard #J8Stream Functional interface Definition: an interface with only one abstract method (methods from Object do not count) (default & static methods do not count) It « can » be annotated by @FunctionalInterface If present: the Java 8 compiler will help me
  42. 42. @JosePaumard #J8Stream In fact… Consumer is a bit more complex than that: @FunctionalInterface public interface Consumer<T> { void accept(T t) ; default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
  43. 43. @JosePaumard #J8Stream In fact… What is a default method? @FunctionalInterface public interface Consumer<T> { void accept(T t) ; default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
  44. 44. @JosePaumard #J8Stream Default methods New concept in Java 8!
  45. 45. @JosePaumard #J8Stream Default methods New concept in Java 8! Added to allow the adding of methods in interfaces without breaking the old implementations
  46. 46. @JosePaumard #J8Stream Default methods New concept in Java 8! Added to allow the adding of methods in interfaces without breaking the old implementations Ex: stream() on the Collection interface
  47. 47. @JosePaumard #J8Stream Collection.stream() public interface Collection<E> { default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } }
  48. 48. @JosePaumard #J8Stream Collection.stream() public interface Collection<E> { default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } default Spliterator<E> spliterator() { return Spliterators.spliterator(this, 0); } }
  49. 49. @JosePaumard #J8Stream Back to the Consumer interface @FunctionalInterface public interface Consumer<T> { void accept(T t) ; default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
  50. 50. @JosePaumard #J8Stream Back to the Consumer interface List<String> list = new ArrayList<>() ; Consumer<String> c1 = s -> list.add(s) ; Consumer<String> c2 = s -> System.out.println(s) ;
  51. 51. @JosePaumard #J8Stream Back to the Consumer interface List<String> list = new ArrayList<>() ; Consumer<String> c1 = list::add ; Consumer<String> c2 = System.out::println ;
  52. 52. @JosePaumard #J8Stream Back to the Consumer interface List<String> list = new ArrayList<>() ; Consumer<String> c1 = list::add ; Consumer<String> c2 = System.out::println ; Consumer<String> c3 = c1.andThen(c2) ; // and we could chain more
  53. 53. @JosePaumard #J8Stream Back to the Consumer interface Beware concurrency! List<String> result = new ArrayList<>() ; List<Person> persons = ... ; Consumer<String> c1 = list::add ; persons.stream() .forEach(c1) ; // concurrency?
  54. 54. @JosePaumard #J8Stream Back to the Consumer interface Beware concurrency! List<String> result = new ArrayList<>() ; List<Person> persons = ... ; Consumer<String> c1 = list::add ; persons.stream().parallel() .forEach(c1) ; // concurrency?
  55. 55. @JosePaumard #J8Stream Back to the Consumer interface Beware concurrency! List<String> result = new ArrayList<>() ; List<Person> persons = ... ; Consumer<String> c1 = list::add ; persons.stream().parallel() .forEach(c1) ; // concurrency? Baaaad pattern!
  56. 56. @JosePaumard #J8Stream Back to the Consumer interface Problem: forEach() returns void List<String> result = new ArrayList<>() ; List<Person> persons = ... ; Consumer<String> c1 = list::add ; Consumer<String> c2 = System.out::println persons.stream() .forEach(c1.andThen(c2)) ;
  57. 57. @JosePaumard #J8Stream Back to the Consumer interface But I also have a peek() method That returns another Stream List<String> result = new ArrayList<>() ; List<Person> persons = ... ; persons.stream() .peek(System.out::println) .filter(person -> person.getAge() > 20) .peek(result::add) ; // Baaad pattern !
  58. 58. @JosePaumard #J8Stream Back to Stream So far we saw: -forEach(Consumer) -peek(Consumer)
  59. 59. @JosePaumard #J8Stream Back to Stream 3rd method: filter(Predicate)
  60. 60. @JosePaumard #J8Stream Method filter() 3rd method: filter(Predicate) List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  61. 61. @JosePaumard #J8Stream Method filter() 3rd method: filter(Predicate) Predicate<Person> p = person -> person.getAge() > 20 ; List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  62. 62. @JosePaumard #J8Stream Interface Predicate Another functional interface @FunctionalInterface public interface Predicate<T> { boolean test(T t) ; }
  63. 63. @JosePaumard #J8Stream Interface Predicate In fact Predicate looks like this: @FunctionalInterface public interface Predicate<T> { boolean test(T t) ; default Predicate<T> and(Predicate<? super T> other) { ... } default Predicate<T> or(Predicate<? super T> other) { ... } default Predicate<T> negate() { ... } }
  64. 64. @JosePaumard #J8Stream Interface Predicate default Predicate<T> and(Predicate<? super T> other) { return t -> test(t) && other.test(t) ; } default Predicate<T> or(Predicate<? super T> other) { return t -> test(t) || other.test(t) ; } default Predicate<T> negate() { return t -> !test(t) ; }
  65. 65. @JosePaumard #J8Stream Interface Predicate: patterns Predicate<Integer> p1 = i -> i > 20 ; Predicate<Integer> p2 = i -> i < 30 ; Predicate<Integer> p3 = i -> i == 0 ;
  66. 66. @JosePaumard #J8Stream Interface Predicate: patterns Predicate<Integer> p1 = i -> i > 20 ; Predicate<Integer> p2 = i -> i < 30 ; Predicate<Integer> p3 = i -> i == 0 ; Predicate<Integer> p = p1.and(p2).or(p3) ; // (p1 AND p2) OR p3
  67. 67. @JosePaumard #J8Stream Interface Predicate: patterns Predicate<Integer> p1 = i -> i > 20 ; Predicate<Integer> p2 = i -> i < 30 ; Predicate<Integer> p3 = i -> i == 0 ; Predicate<Integer> p = p1.and(p2).or(p3) ; // (p1 AND p2) OR p3 Predicate<Integer> p = p3.or(p1).and(p2) ; // (p3 OR p1) AND p2
  68. 68. @JosePaumard #J8Stream Interface Predicate In fact Predicate looks like this (bis): @FunctionalInterface public interface Predicate<T> { boolean test(T t) ; // default methods static <T> Predicate<T> isEqual(Object o) { ... } }
  69. 69. @JosePaumard #J8Stream Interface Predicate static <T> Predicate<T> isEqual(Object o) { return t -> o.equals(t) ; }
  70. 70. @JosePaumard #J8Stream Interface Predicate In fact things are bit more complicated: static <T> Predicate<T> isEqual(Object o) { return t -> o.equals(t) ; } static <T> Predicate<T> isEqual(Object o) { return (null == o) ? obj -> Objects.isNull(obj) : t -> o.equals(t) ; }
  71. 71. @JosePaumard #J8Stream Interface Predicate In fact things are bit more complicated: static <T> Predicate<T> isEqual(Object o) { return t -> o.equals(t) ; } static <T> Predicate<T> isEqual(Object o) { return (null == o) ? Objects::isNull : o::equals ; }
  72. 72. @JosePaumard #J8Stream Interface Predicate We also have: @FunctionalInterface public interface BiPredicate<T, U> { boolean test(T t, U u); }
  73. 73. @JosePaumard #J8Stream Filtered Streams In this code: stream and filtered are different objects The filter() method returns a new object List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  74. 74. @JosePaumard #J8Stream Filtered Streams In this code: Question 1: what do we have in the filtered object? List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  75. 75. @JosePaumard #J8Stream Filtered Streams In this code: Question 1: what do we have in the filtered object? Answer: the filtered data! List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  76. 76. @JosePaumard #J8Stream Filtered Streams In this code: Question 1: what do we have in the filtered object? Answer: the filtered data… really? List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  77. 77. @JosePaumard #J8Stream Filtered Streams In this code: Question 1: what do we have in the filtered object? Didnt we say: « a stream does not hold any data »? List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  78. 78. @JosePaumard #J8Stream Filtered Streams In this code: Question 1: what do we have in the filtered object? Correct answer: nothing! List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  79. 79. @JosePaumard #J8Stream Filtered Streams In this code: Question 2: what does this code do? List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  80. 80. @JosePaumard #J8Stream Filtered Streams In this code: Question 2: what does this code do? Answer: nothing… List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  81. 81. @JosePaumard #J8Stream Filtered Streams In this code: Question 2: what does this code do? Answer: nothing… This call is a declaration, no data is processed! List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<Person> filtered = stream.filter(person -> person.getAge() > 20) ;
  82. 82. @JosePaumard #J8Stream Filtered Streams The filter() call is a lazy call Generally speaking: A call to a method that returns a Stream is a lazy call
  83. 83. @JosePaumard #J8Stream Filtered Streams The filter() call is a lazy call Another way of saying it: An operation that returns a Stream is an intermediate operation
  84. 84. @JosePaumard #J8Stream Intermediate call Stating that a Stream does not hold any data creates the notion of intermediate operation adds the notion of lazyness to the Stream API
  85. 85. @JosePaumard #J8Stream Intermediate call Stating that a Stream does not hold any data creates the notion of intermediate operation adds the notion of lazyness to the Stream API There must be some kind terminal operation somewhere…
  86. 86. @JosePaumard #J8Stream Back to Consumer (bis) What happens in that code? List<String> result = new ArrayList<>() ; List<Person> persons = ... ; persons.stream() .peek(System.out::println) .filter(person -> person.getAge() > 20) .peek(resultat::add) ; // Baaad pattern !
  87. 87. @JosePaumard #J8Stream Back to Consumer (bis) What happens in that code? Answer is: nothing! List<String> result = new ArrayList<>() ; List<Person> persons = ... ; persons.stream() .peek(System.out::println) .filter(person -> person.getAge() > 20) .peek(result::add) ; // Baaad pattern !
  88. 88. @JosePaumard #J8Stream Back to Consumer (bis) What happens in that code? 1) nothing displayed 2) result is empty List<String> result = new ArrayList<>() ; List<Person> persons = ... ; persons.stream() .peek(System.out::println) .filter(person -> person.getAge() > 20) .peek(result::add) ; // Baaad pattern !
  89. 89. @JosePaumard #J8Stream What do we have so far? We saw: -forEach(Consumer) -peek(Consumer) -filter(Predicate)
  90. 90. @JosePaumard #J8Stream What do we have so far? We saw: -forEach(Consumer) -peek(Consumer) -filter(Predicate) The notion of lazyness / intermediate call
  91. 91. @JosePaumard #J8Stream Let us carry on And see the mapping operation
  92. 92. @JosePaumard #J8Stream Mapping Mapping operation List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<String> names = stream.map(person -> person.getName()) ;
  93. 93. @JosePaumard #J8Stream Mapping Mapping operation The map() method returns a Stream It is thus lazy / intermediate List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<String> names = stream.map(person -> person.getName()) ;
  94. 94. @JosePaumard #J8Stream Interface Function The map() method takes a Function: @FunctionalInterface public interface Function<T, R> { R apply(T t) ; }
  95. 95. @JosePaumard #J8Stream Interface Function Which in fact is: @FunctionalInterface public interface Function<T, R> { R apply(T t) ; default <V> Function<V, R> compose(Function<V, T> before) ; default <V> Function<T, V> andThen(Function<R, V> after) ; }
  96. 96. @JosePaumard #J8Stream Interface Function Which in fact is: Beware the generics! @FunctionalInterface public interface Function<T, R> { R apply(T t) ; default <V> Function<V, R> compose(Function<V, T> before) ; default <V> Function<T, V> andThen(Function<R, V> after) ; }
  97. 97. @JosePaumard #J8Stream Interface Function Which in fact is: @FunctionalInterface public interface Function<T, R> { R apply(T t) ; default <V> Function<V, R> compose( Function<? super V, ? extends T> before) ; default <V> Function<T, V> andThen( Function<? super R, ? extends V> after) ; }
  98. 98. @JosePaumard #J8Stream Interface Function Which in fact is: @FunctionalInterface public interface Function<T, R> { R apply(T t) ; // default methods static <T> Function<T, T> identity() { return t -> t ; } }
  99. 99. @JosePaumard #J8Stream Other functions There are special types of functions: @FunctionalInterface public interface UnaryOperator<T> extends Function<T, T> { }
  100. 100. @JosePaumard #J8Stream Other functions There are special types of functions: @FunctionalInterface public interface BiFunction<T, U, R> { R apply(T t, U u); }
  101. 101. @JosePaumard #J8Stream Other functions There are special types of functions: @FunctionalInterface public interface BinaryOperator<T> extends BiFunction<T, T, T> { }
  102. 102. @JosePaumard #J8Stream What do we have so far? We saw: -forEach(Consumer) -peek(Consumer) -filter(Predicate) -map(Function)
  103. 103. @JosePaumard #J8Stream Let us carry on Method flatMap()
  104. 104. @JosePaumard #J8Stream Method flatMap() flatMap() = flattens a Stream The signature is: The passed function returns a Stream <R> Stream<R> flatMap(Function<T, Stream<R>> mapper) ;
  105. 105. @JosePaumard #J8Stream Method flatMap() Let us take an example: List<Movie> movies = ... ; // a movie has a set of Actor movies.stream() .map(movie -> movie.actors()) // Stream<Set<Actors>>
  106. 106. @JosePaumard #J8Stream Method flatMap() Let us take an example: List<Movie> movies = ... ; // a movie has a set of Actor movies.stream() .map(movie -> movie.actors().stream()) // Stream<Stream<Actors>>
  107. 107. @JosePaumard #J8Stream Method flatMap() Let us take an example: List<Movie> movies = ... ; // a movie has a set of Actor movies.stream() .map(movie -> movie.actors().stream()) // Stream<Stream<Actors>> Function<Movie, Stream<Actors>> mapper = movie -> movie.actors().stream();
  108. 108. @JosePaumard #J8Stream Method flatMap() Let us take an example: List<Movie> movies = ... ; // a movie has a set of Actor movies.stream() .flatMap(movie -> movie.actors().stream()) // Stream<Actors>
  109. 109. @JosePaumard #J8Stream Method flatMap() flatMap() = flattens a Stream Signature: <R> Stream<R> flatMap(Function<T, Stream<R>> mapper) ;
  110. 110. @JosePaumard #J8Stream Method flatMap() flatMap() = flattens a Stream Signature: Since it returns a Stream, it is a lazy / intermediate call <R> Stream<R> flatMap(Function<T, Stream<R>> mapper) ;
  111. 111. @JosePaumard #J8Stream What do we have so far? We have 3 types of methods: -forEach(): consumes -peek(): consumes, and transmits -filter(): filters -map(): transforms -flatMap(): transforms and flattens
  112. 112. @JosePaumard #J8Stream What do we have so far? And what about reductions?
  113. 113. @JosePaumard #J8Stream Reduction Reduction method: List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, (age1, age2) -> age1 + age2) ;
  114. 114. @JosePaumard #J8Stream Reduction Reduction method: Two things to stress out here List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, (age1, age2) -> age1 + age2) ;
  115. 115. @JosePaumard #J8Stream Reduction Reduction method: Two things to stress out here List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, Intege::sum) ;
  116. 116. @JosePaumard #J8Stream Reduction Reduction method: 0 is the « default value » of the reduction operation returned if the stream is « empty » List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, (age1, age2) -> age1 + age2) ;
  117. 117. @JosePaumard #J8Stream Reduction Reduction method: 0 is the « default value » of the reduction operation This « default value » has to be the identity element of the reduction operation List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, (age1, age2) -> age1 + age2) ;
  118. 118. @JosePaumard #J8Stream Reduction Reduction method: 0 is the « default value » of the reduction operation If it is not, then the computation will fail! List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, (age1, age2) -> age1 + age2) ;
  119. 119. @JosePaumard #J8Stream Reduction Why? -This 0 is returned in case of an empty Stream -Red(0, p) is returned in case of a singleton Stream In fact, 0 is used to compute the reduction of the Stream
  120. 120. @JosePaumard #J8Stream Reduction What is going to happen if the reduction operation has no identity value?
  121. 121. @JosePaumard #J8Stream Reduction What is going to happen if the reduction operation has no identity value? But of course we do not use such reductions…
  122. 122. @JosePaumard #J8Stream Reduction Reduction method: The reduction operation should be associative List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, (age1, age2) -> age1 + age2) ;
  123. 123. @JosePaumard #J8Stream Reduction Reduction method: The reduction operation should be associative If not, we will have trouble in parallel List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, (age1, age2) -> age1 + age2) ;
  124. 124. @JosePaumard #J8Stream Reduction Associative, or not associative? red1 = (i1, i2) -> i1 + i2 ;
  125. 125. @JosePaumard #J8Stream Reduction Associative, or not associative? red1 = (i1, i2) -> i1 + i2 ;  red2 = (i1, i2) -> i1 > i2 ? i1 : i2 ;
  126. 126. @JosePaumard #J8Stream Reduction Associative, or not associative? red1 = (i1, i2) -> i1 + i2 ;  red2 = (i1, i2) -> i1 > i2 ? i1 : i2 ;  red3 = (i1, i2) -> i1*i2 ;
  127. 127. @JosePaumard #J8Stream Reduction Associative, or not associative? red1 = (i1, i2) -> i1 + i2 ;  red2 = (i1, i2) -> i1 > i2 ? i1 : i2 ;  red3 = (i1, i2) -> i1*i2 ;  red4 = (i1, i2) -> i1*i1 + i2*i2 ;
  128. 128. @JosePaumard #J8Stream Reduction Associative, or not associative? red1 = (i1, i2) -> i1 + i2 ;  red2 = (i1, i2) -> i1 > i2 ? i1 : i2 ;  red3 = (i1, i2) -> i1*i2 ;  red4 = (i1, i2) -> i1*i1 + i2*i2 ;  red5 = (i1, i2) -> (i1 + i2) / 2 ;
  129. 129. @JosePaumard #J8Stream Reduction Associative, or not associative? red1 = (i1, i2) -> i1 + i2 ;  red2 = (i1, i2) -> i1 > i2 ? i1 : i2 ;  red3 = (i1, i2) -> i1*i2 ;  red4 = (i1, i2) -> i1*i1 + i2*i2 ;  red5 = (i1, i2) -> (i1 + i2) / 2 ;  red6 = (i1, i2) -> i2 ;
  130. 130. @JosePaumard #J8Stream Reduction Associative, or not associative? red1 = (i1, i2) -> i1 + i2 ;  red2 = (i1, i2) -> i1 > i2 ? i1 : i2 ;  red3 = (i1, i2) -> i1*i2 ;  red4 = (i1, i2) -> i1*i1 + i2*i2 ;  red5 = (i1, i2) -> (i1 + i2) / 2 ;  red6 = (i1, i2) -> i2 ; 
  131. 131. @JosePaumard #J8Stream Example of max Let us reduce with a max List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer max = stream.reduce(0, (age1, age2) -> age1 > age2 ? age1 : age2) ;
  132. 132. @JosePaumard #J8Stream Example of max Let us reduce with a max List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer max = stream.reduce(0, Integer::max) ;
  133. 133. @JosePaumard #J8Stream Example of max Let us reduce with a max List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer max = stream.reduce(0, (age1, age2) -> age1 > age2 ? age1 : age2) ; List<Integer> ages = new ArrayList<>() ; Stream<Integer> stream = ages.stream() ; // empty stream > max = 0
  134. 134. @JosePaumard #J8Stream Example of max Let us reduce with a max List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer max = stream.reduce(0, (age1, age2) -> age1 > age2 ? age1 : age2) ; List<Integer> ages = Arrays.asList(2) ; Stream<Integer> stream = ages.stream() ; // singleton stream > max = 2
  135. 135. @JosePaumard #J8Stream Example of max Let us reduce with a max List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer max = stream.reduce(0, (age1, age2) -> age1 > age2 ? age1 : age2) ; List<Integer> ages = Arrays.asList(-1) ; Stream<Integer> stream = ages.stream() ; // singleton stream > max = 0
  136. 136. @JosePaumard #J8Stream Example of max Let us reduce with a max List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer max = stream.reduce(0, (age1, age2) -> age1 > age2 ? age1 : age2) ; List<Integer> ages = Arrays.asList(-1, -2) ; Stream<Integer> stream = ages.stream() ; > max = 0
  137. 137. @JosePaumard #J8Stream Example of max The reduction with a max has a problem : why?
  138. 138. @JosePaumard #J8Stream Example of max The reduction with a max has a problem : why? Answer: the max reduction has no identity element, thus no default value
  139. 139. @JosePaumard #J8Stream Example of max The reduction with a max has a problem : why? Answer: the max reduction has no identity element, thus no default value Solution: introduce the notion of Optional
  140. 140. @JosePaumard #J8Stream Method max() Optional is the return type of the max() method List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Optional<Integer> max = stream.max(Comparator.naturalOrder()) ;
  141. 141. @JosePaumard #J8Stream Optional An Optional is a wrapping type, that can be empty How can I use it? Optional<String> opt = ... ; if (opt.isPresent()) { String s = opt.get() ; } else { ... }
  142. 142. @JosePaumard #J8Stream Optional An Optional is a wrapping type, that can be empty How can I use it? String s = opt.orElse("") ; // this is a default value that // is valid for our application Optional<String> opt = ... ; if (opt.isPresent()) { String s = opt.get() ; } else { ... }
  143. 143. @JosePaumard #J8Stream Optional An Optional is a wrapping type, that can be empty How can I use it? String s = opt.orElseThrow(MyException::new) ; // lazy initialization
  144. 144. @JosePaumard #J8Stream Optional can be built One can explicitly build optionals Optional<String> opt = Optional.<String>empty() ; Optional<String> opt = Optional.of("one") ; // not null Optional<String> opt = Optional.ofNullable(s) ; // may be null
  145. 145. @JosePaumard #J8Stream Optional: more patterns An Optional can be seen as a special Stream with zero or one element void ifPresent(Consumer<T> consumer) ;
  146. 146. @JosePaumard #J8Stream Optional: more patterns An Optional can be seen as a special Stream with zero or one element void ifPresent(Consumer<T> consumer) ; Optional<T> filter(Predicate<T> mapper) ;
  147. 147. @JosePaumard #J8Stream Optional: more patterns An Optional can be seen as a special Stream with zero or one element void ifPresent(Consumer<T> consumer) ; Optional<T> filter(Predicate<T> mapper) ; Optional<U> map(Function<T, U> mapper) ;
  148. 148. @JosePaumard #J8Stream Optional: more patterns An Optional can be seen as a special Stream with zero or one element void ifPresent(Consumer<T> consumer) ; Optional<T> filter(Predicate<T> mapper) ; Optional<U> map(Function<T, U> mapper) ; Optional<U> flatMap(Function<T, Optional<U>> mapper) ;
  149. 149. @JosePaumard #J8Stream Optional: new patterns sighted! public class NewMath { public static Optional<Double> inv(Double d) { return d == 0.0d ? Optional.empty() : Optional.of(1/d) ; } public static Optional<Double> sqrt(Double d) { return d < 0.0d ? Optional.empty() : Optional.of(Math.sqrt(d)) ; } }
  150. 150. @JosePaumard #J8Stream Optional: new patterns sighted! List<Double> doubles = Arrays.asList(-1d, 0d, 1d) ; List<Double> result = new ArrayList<>() ; doubles.forEach( d1 -> NewMath.inv(d1) // Optional<Double> .flatMap(d2 -> NewMath.sqrt(d2)) // Optional<Double> .ifPresent(result::add) ) ; doubles : [-1.0, 0.0, 1.0] result : [1.0]
  151. 151. @JosePaumard #J8Stream Optional: new patterns sighted! List<Double> doubles = Arrays.asList(-1d, 0d, 1d) ; List<Double> result = new ArrayList<>() ; doubles.forEach( d1 -> NewMath.inv(d1) // Optional<Double> .flatMap(d2 -> NewMath.sqrt(d2)) // Optional<Double> .ifPresent(result::add) ) ; doubles : [-1.0, 0.0, 1.0] result : [1.0]
  152. 152. @JosePaumard #J8Stream Optional: new patterns sighted! Function<Double, Optional<Double>> f = d -> NewMath.inv(d) // Optional<Double> .flatMap(d -> NewMath.sqrt(d))// Optional<Double>
  153. 153. @JosePaumard #J8Stream Optional: new patterns sighted! Function<Double, Optional<Double>> f = d -> NewMath.inv(d) // Optional<Double> .flatMap(NewMath::sqrt); // Optional<Double>
  154. 154. @JosePaumard #J8Stream Optional: new patterns sighted! d -> NewMath.inv(d) // Optional<Double> .flatMap(NewMath::sqrt) // Optional<Double> .map(Stream::of) // Optional<Stream<Double>>
  155. 155. @JosePaumard #J8Stream Optional: new patterns sighted! d -> NewMath.inv(d) // Optional<Double> .flatMap(NewMath::sqrt) // Optional<Double> .map(Stream::of) // Optional<Stream<Double>> .orElse(Stream.empty()) // Stream<Double>
  156. 156. @JosePaumard #J8Stream Optional: new patterns sighted! Function<Double, Stream<Double>> f = d -> NewMath.inv(d) // Optional<Double> .flatMap(NewMath::sqrt) // Optional<Double> .map(Stream::of) // Optional<Stream<Double>> .orElse(Stream.empty()) ; // Stream<Double>
  157. 157. @JosePaumard #J8Stream Optional: new patterns sighted! List<Double> doubles = Arrays.asList(-1d, 0d, 1d) ; List<Double> result = new ArrayList<>() ; doubles.stream() .flatMap( d -> NewMath.inv(d) // Optional<Double> .flatMap(NewMath::sqrt) // Optional<Double> .map(Stream::of) // Optional<Stream<Double>> .orElse(Stream.empty()) // Stream<Double> ) // Stream<Double>
  158. 158. @JosePaumard #J8Stream Optional: new patterns sighted! List<Double> doubles = Arrays.asList(-1d, 0d, 1d) ; List<Double> result = new ArrayList<>() ; doubles.stream() .flatMap( d -> NewMath.inv(d) // Optional<Double> .flatMap(NewMath::sqrt) // Optional<Double> .map(Stream::of) // Optional<Stream<Double>> .orElse(Stream.empty()) // Stream<Double> ) // Stream<Double> .collect(Collectors.toList()) ;
  159. 159. @JosePaumard #J8Stream Back on the reduce() method Two return types: List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, (age1, age2) -> age1 + age2) ; List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Optional<Integer> opt = stream.reduce((age1, age2) -> age1 + age2) ;
  160. 160. @JosePaumard #J8Stream Back on the reduce() method Two return types: List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, Integer::sum) ; List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Optional<Integer> opt = stream.reduce(Integer::sum) ;
  161. 161. @JosePaumard #J8Stream More on the reduction A reduction never returns a Stream -max(), min() [optionals] -count() Boolean reductions: -allMatch(), noneMatch, anyMatch() Return optionals: -findFirst(), findAny() (parallel!)
  162. 162. @JosePaumard #J8Stream Note on the reduction A reduction never returns a Stream So it is not a lazy step / intermediate operation A reduction always triggers the computation They are terminal operations
  163. 163. @JosePaumard #J8Stream Terminal operation Example List<Person> persons = ... ; ... = persons.map(person -> person.getAge()) // Stream<Integer> .filter(age -> age > 20) // Stream<Integer> .min(Comparator.naturalOrder()) ;
  164. 164. @JosePaumard #J8Stream Terminal operation Example List<Person> persons = ... ; ... = persons.map(Person::getAge) // Stream<Integer> .filter(age -> age > 20) // Stream<Integer> .min(Comparator.naturalOrder()) ;
  165. 165. @JosePaumard #J8Stream Terminal operation Let us write a full map / filter / reduce List<Person> persons = ... ; Optional<Integer> age = persons.map(person -> person.getAge()) // Stream<Integer> .filter(age -> age > 20) // Stream<Integer> .min(Comparator.naturalOrder()) ; // terminal operation
  166. 166. @JosePaumard #J8Stream Terminal operation Let us write a full map / filter / reduce List<Person> persons = ... ; boolean b = persons.map(person -> person.getLastName()) .allMatch(length < 20) ; // terminal operation
  167. 167. @JosePaumard #J8Stream Terminal operation Let us write a full map / filter / reduce List<Person> persons = ... ; boolean b = persons.map(Person::getAge) .allMatch(length < 20) ; // terminal operation
  168. 168. @JosePaumard #J8Stream Terminal operation Let us write a full map / filter / reduce Much more efficient to compute this in one pass over the data: « short cutting methods » List<Person> persons = ... ; boolean b = persons.map(Person::getAge) .allMatch(length < 20) ; // terminal operation
  169. 169. @JosePaumard #J8Stream What is a Stream? An object on which we can define operations on data No a priori limit on the size of the data Typical operations: map / filter / reduce
  170. 170. @JosePaumard #J8Stream What is a Stream? Pipeline approach: 1)we define the operations 2)we trigger the computations by calling a terminal operation
  171. 171. @JosePaumard #J8Stream What is a Stream? And bytheway: We can only have one terminal operation for a Stream In case, another Stream must be built
  172. 172. @JosePaumard #J8Stream How one can build a Stream? Let us have a look at the stream() default method List<Person> persons = new ArrayList<>() ; Stream<Person> stream = persons.stream() ; // Collection interface default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); }
  173. 173. @JosePaumard #J8Stream How one can build a Stream? Let us have a look at the stream() default method // StreamSupport class public static <T> Stream<T> stream( Spliterator<T> spliterator, boolean parallel) { Objects.requireNonNull(spliterator) ; return new ReferencePipeline.Head<>( spliterator, StreamOpFlag.fromCharacteristics(spliterator), parallel) ; }
  174. 174. @JosePaumard #J8Stream How one can build a Stream? The spliterator() is defined in ArrayList // ArrayList class @Override public Spliterator<E> spliterator() { return new ArrayListSpliterator<>(this, 0, -1, 0); }
  175. 175. @JosePaumard #J8Stream How one can build a Stream? The spliterator() is defined in ArrayList The Spliterator defines how to access the data ArrayList: it reads the array // ArrayList class @Override public Spliterator<E> spliterator() { return new ArrayListSpliterator<>(this, 0, -1, 0); }
  176. 176. @JosePaumard #J8Stream Spliterator Let us see the method we need to implement Consumes the next element, if it exists // Spliterator interface boolean tryAdvance(Consumer<? super T> action);
  177. 177. @JosePaumard #J8Stream Spliterator Let us see the method we need to implement Consumes the next element, if it exists A Stream does not assume that all the elements are available at build time // Spliterator interface boolean tryAdvance(Consumer<? super T> action);
  178. 178. @JosePaumard #J8Stream Spliterator Let us see the method we need to implement Used in parallel computations: tries to split the data in two (fork / join) // Spliterator interface Spliterator<T> trySplit();
  179. 179. @JosePaumard #J8Stream Spliterator Let us see the method we need to implement Returns an estimation of the size of this stream // Spliterator interface long estimateSize();
  180. 180. @JosePaumard #J8Stream Spliterator And there are also default methods // Spliterator interface default void forEachRemaining(Consumer<? super T> action) { do { } while (tryAdvance(action)); } // Spliterator interface default long getExactSizeIfKnown() { return (characteristics() & SIZED) == 0 ? -1L : estimateSize(); }
  181. 181. @JosePaumard #J8Stream Spliterator And there is a last method: Implémentation for ArrayList // interface Spliterator int characteristics(); // pour ArrayList public int characteristics() { return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; }
  182. 182. @JosePaumard #J8Stream Spliterator And there is a last method: Implémentation for HashSet // interface Spliterator int characteristics(); // pour HashSet public int characteristics() { return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) | Spliterator.DISTINCT; }
  183. 183. @JosePaumard #J8Stream Characteristics of a Stream Bits defined in the characteristics word Characteristic ORDERED The order matters DISTINCT No duplication SORTED Sorted SIZED The size is known NONNULL No null values IMMUTABLE Immutable CONCURRENT Parallelism is possible SUBSIZED The size is known
  184. 184. @JosePaumard #J8Stream Characteristics of a Stream Some operations will switch some bits Method Set to 0 Set to 1 filter() SIZED - map() DISTINCT, SORTED - flatMap() DISTINCT, SORTED, SIZED - sorted() - SORTED, ORDERED distinct() - DISTINCT limit() SIZED - peek() - - unordered() ORDERED -
  185. 185. @JosePaumard #J8Stream Characteristics of a Stream Characteristics are taken into account when computing a result // HashSet HashSet<String> strings = ... ; strings.stream() .distinct() // no processing is triggered .sorted() .collect(Collectors.toList()) ;
  186. 186. @JosePaumard #J8Stream Characteristics of a Stream Characteristics are taken into account when computing a result // SortedSet TreeSet<String> strings = ... ; strings.stream() .distinct() .sorted() // no processing is triggered .collect(Collectors.toList()) ;
  187. 187. @JosePaumard #J8Stream Stream implementation Complex! Two parts: 1)algorithms are in ReferencePipeline 2)data access: Spliterator, can be overriden
  188. 188. @JosePaumard #J8Stream A few words on Comparator We wrote: // Comparator interface Comparator cmp = Comparator.naturalOrder() ;
  189. 189. @JosePaumard #J8Stream A few words on Comparator We wrote: // Comparator interface Comparator cmp = Comparator.naturalOrder() ; // Comparator interface @SuppressWarnings("unchecked") public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() { return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE; }
  190. 190. @JosePaumard #J8Stream A few words on Comparator // Comparators class enum NaturalOrderComparator implements Comparator<Comparable<Object>> { INSTANCE; }
  191. 191. @JosePaumard #J8Stream A few words on Comparator // Comparators class enum NaturalOrderComparator implements Comparator<Comparable<Object>> { INSTANCE; } public class MySingleton { INSTANCE; private MySingleton() {} public static MySingleton getInstance() { // some buggy double-checked locking code return INSTANCE; } }
  192. 192. @JosePaumard #J8Stream A few words on Comparator // Comparators class enum NaturalOrderComparator implements Comparator<Comparable<Object>> { INSTANCE; public int compare(Comparable<Object> c1, Comparable<Object> c2) { return c1.compareTo(c2); } public Comparator<Comparable<Object>> reversed() { return Comparator.reverseOrder(); } }
  193. 193. @JosePaumard #J8Stream A few words on Comparator So we can write: // Comparator interface Comparator<Person> cmp = Comparator.comparing(Person::getLastName) .thenComparing(Person::getFirstName) .thenComparing(Person::getAge) ;
  194. 194. @JosePaumard #J8Stream A few words on Comparator Method comparing() // Comparator interface public static <T, U> Comparator<T> comparing(Function<T, U> keyExtractor) { Objects.requireNonNull(keyExtractor); return (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); }
  195. 195. @JosePaumard #J8Stream A few words on Comparator Method comparing() // Comparator interface public static <T, U extends Comparable<U>> Comparator<T> comparing(Function<T, U> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T>) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); }
  196. 196. @JosePaumard #J8Stream A few words on Comparator Method comparing() // Comparator interface public static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); }
  197. 197. @JosePaumard #J8Stream A few words on Comparator Method thenComparing() // Comparator interface default <U> Comparator<T> thenComparing(Function<T, U> keyExtractor) { return thenComparing(comparing(keyExtractor)); }
  198. 198. @JosePaumard #J8Stream A few words on Comparator Method thenComparing() // Comparator interface default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor) { return thenComparing(comparing(keyExtractor)); }
  199. 199. @JosePaumard #J8Stream A few words on Comparator Method thenComparing() // Comparator interface default Comparator<T> thenComparing(Comparator<? super T> other) { Objects.requireNonNull(other); return (Comparator<T> & Serializable) (c1, c2) -> { int res = compare(c1, c2); return (res != 0) ? res : other.compare(c1, c2); }; }
  200. 200. @JosePaumard #J8Stream What do we have so far? API Stream -intermediate operations -terminal operations -implementation built on 2 classes
  201. 201. @JosePaumard #J8Stream Stateless / stateful operations This code: … selects the 1000 first people of the list ArrayList<Person> persons = ... ; Stream<Persons> stream = persons.limit(1_000) ;
  202. 202. @JosePaumard #J8Stream Stateless / stateful operations This code: … selects the 1000 first people of the list This operations needs a counter How will it work in parallel? ArrayList<Person> persons = ... ; Stream<Persons> stream = persons.limit(1_000) ;
  203. 203. @JosePaumard #J8Stream Stateless / stateful operations This code: ArrayList<Person> persons = ... ; List<String> names = persons.map(Person::getLastName) .collect(Collectors.toList()) ;
  204. 204. @JosePaumard #J8Stream Stateless / stateful operations This code: « the order of the names is the same as the order of the people » ArrayList<Person> persons = ... ; List<String> names = persons.map(Person::getLastName) .collect(Collectors.toList()) ;
  205. 205. @JosePaumard #J8Stream Stateless / stateful operations This code: « the order of the names is the same as the order of the people » How will it behave in parallel? ArrayList<Person> persons = ... ; List<String> names = persons.map(Person::getLastName) .collect(Collectors.toList()) ;
  206. 206. @JosePaumard #J8Stream Stateless / stateful operations This code: « the order of the names is the same as the order of the people » We should relax this constraint! ArrayList<Person> persons = ... ; List<String> names = persons.map(Person::getLastName) .unordered() .collect(Collectors.toList()) ;
  207. 207. @JosePaumard #J8Stream Wrap-up on Stream One can define operations on a Stream: -intermediate & terminal -stateless & stateful A Stream can be processed in parallel A Stream has a state, used to optimize computations
  208. 208. @JosePaumard #J8Stream Stream & performance Two elements: -lazy processing, on one pass over the data -parallel processing
  209. 209. @JosePaumard #J8Stream Stream & performance Two elements: -lazy processing, on one pass over the data -parallel processing Stream<T> versus IntStream, LongStream, DoubleStream
  210. 210. @JosePaumard #J8Stream Stream & performance Let see this example again: ArrayList<Person> persons = ... ; persons.stream() .map(Person::getAge) .filter(age -> age > 20) .sum() ;
  211. 211. @JosePaumard #J8Stream Stream & performance Let see this example again: ArrayList<Person> persons = ... ; persons.stream() // Stream<Person> .map(Person::getAge) .filter(age -> age > 20) .sum() ;
  212. 212. @JosePaumard #J8Stream Stream & performance Let see this example again: ArrayList<Person> persons = ... ; persons.stream() // Stream<Person> .map(Person::getAge) // Stream<Integer> boxing  .filter(age -> age > 20) .sum() ;
  213. 213. @JosePaumard #J8Stream Stream & performance Let see this example again: ArrayList<Person> persons = ... ; persons.stream() // Stream<Person> .map(Person::getAge) // Stream<Integer> boxing  .filter(age -> age > 20) // Stream<Integer> re-boxing re- .sum() ;
  214. 214. @JosePaumard #J8Stream Stream & performance Let see this example again: ArrayList<Person> persons = ... ; persons.stream() // Stream<Person> .map(Person::getAge) // Stream<Integer> boxing  .filter(age -> age > 20) // Stream<Integer> re-boxing re- .sum() ; // no such sum() method on Stream<T>
  215. 215. @JosePaumard #J8Stream Stream & performance Let see this example again ArrayList<Person> persons = ... ; persons.stream() // Stream<Person> .map(Person::getAge) // Stream<Integer> boxing  .filter(age -> age > 20) // Stream<Integer> re-boxing re- .mapToInt(age -> age.getValue()) // IntStream  .sum() ;
  216. 216. @JosePaumard #J8Stream Stream & performance Let see this example again ArrayList<Person> persons = ... ; persons.stream() // Stream<Person> .map(Person::getAge) // Stream<Integer> boxing  .filter(age -> age > 20) // Stream<Integer> re-boxing re- .mapToInt(Integer::getValue) // IntStream  .sum() ;
  217. 217. @JosePaumard #J8Stream Stream & performance Let see this example again ArrayList<Person> persons = ... ; persons.stream() // Stream<Person> .mapToInt(Person::getAge) // IntStream  .filter(age -> age > 20) // IntStream  // .mapToInt(Integer::getValue) .sum() ;
  218. 218. @JosePaumard #J8Stream Stream & performance Let see this example again ArrayList<Person> persons = ... ; int sum = persons.stream() // Stream<Person> .mapToInt(Person::getAge) // IntStream  .filter(age -> age > 20) // IntStream  // .mapToInt(Integer::getValue) .sum() ;
  219. 219. @JosePaumard #J8Stream Stream & performance Let see this example again ArrayList<Person> persons = ... ; ??? = persons.stream() // Stream<Person> .mapToInt(Person::getAge) // IntStream  .filter(age -> age > 20) // IntStream  // .mapToInt(Integer::getValue) .max() ;
  220. 220. @JosePaumard #J8Stream Stream & performance Let see this example again ArrayList<Person> persons = ... ; OptionalInt opt = persons.stream() // Stream<Person> .mapToInt(Person::getAge) // IntStream  .filter(age -> age > 20) // IntStream  // .mapToInt(Integer::getValue) .max() ;
  221. 221. @JosePaumard #J8Stream Stream & performance Let see this example again ArrayList<Person> persons = ... ; ??? = persons.stream() // Stream<Person> .mapToInt(Person::getAge) // IntStream  .filter(age -> age > 20) // IntStream  // .mapToInt(Integer::getValue) .average() ;
  222. 222. @JosePaumard #J8Stream Stream & performance Let see this example again ArrayList<Person> persons = ... ; OptionalInt opt = persons.stream() // Stream<Person> .mapToInt(Person::getAge) // IntStream  .filter(age -> age > 20) // IntStream  // .mapToInt(Integer::getValue) .average() ;
  223. 223. @JosePaumard #J8Stream Stream & performance Let see this example again sur l’exemple In one pass we have: count, sum, min, max, average ArrayList<Person> persons = ... ; IntSummaryStatistics stats = persons.stream() .mapToInt(Person::getAge) .filter(age -> age > 20) .summaryStatistics() ;
  224. 224. @JosePaumard #J8Stream Parallel streams How to build a parallel Stream? Built on top of fork / join ArrayList<Person> persons = ... ; Stream<Person> stream1 = persons.parallelStream() ; Stream<Person> stream2 = persons.stream().parallel() ;
  225. 225. @JosePaumard #J8Stream Parallel streams By default, a parallel streams uses the default « fork join common pool », defined at the JVM level The same pool is shared by all the streams
  226. 226. @JosePaumard #J8Stream Parallelism By default, a parallel streams uses the default « fork join common pool », defined at the JVM level By default, the parallelism level is the # of cores We can set it with a sytem property: System.setProperty( "java.util.concurrent.ForkJoinPool.common.parallelism", 2) ;
  227. 227. @JosePaumard #J8Stream Parallelism We can also decide the FJ pool for a given Stream List<Person> persons = ... ; ForkJoinPool fjp = new ForkJoinPool(2) ; fjp.submit( () -> // persons.stream().parallel() // this is an implementation .mapToInt(p -> p.getAge()) // of Callable<Integer> .filter(age -> age > 20) // .average() // ).get() ;
  228. 228. @JosePaumard #J8Stream Reduction A reduction can be seen as a SQL agregation (sum, min, max, avg, etc…)
  229. 229. @JosePaumard #J8Stream Reduction A reduction can be seen as a SQL agregation (sum, min, max, avg, etc…) But it can be seen in a more general sense
  230. 230. @JosePaumard #J8Stream Reduction Example: sum()
  231. 231. @JosePaumard #J8Stream Reduction Example: sum() The result is an integer, its initial value being 0
  232. 232. @JosePaumard #J8Stream Reduction Example: sum() The result is an integer, its initial value being 0 Adding an element to the result is… adding
  233. 233. @JosePaumard #J8Stream Reduction Example: sum() The result is an integer, its initial value being 0 Adding an element to the result is… adding Combining two partial results (think parallel) is also « adding »
  234. 234. @JosePaumard #J8Stream Reduction So we have 3 operations:
  235. 235. @JosePaumard #J8Stream Reduction So we have 3 operations: -the definition of a container, which holds the result
  236. 236. @JosePaumard #J8Stream Reduction So we have 3 operations: -the definition of a container, which holds the result -adding an element to that container
  237. 237. @JosePaumard #J8Stream Reduction So we have 3 operations: -the definition of a container, which holds the result -adding an element to that container -combining two partialy filled containers
  238. 238. @JosePaumard #J8Stream Reduction So we have 3 operations: -the definition of a container, which holds the result -adding an element to that container -combining two partialy filled containers This is a much more broader vision than just an agregation
  239. 239. @JosePaumard #J8Stream Reduction So a reduction is based on 3 operations: -a constructor: Supplier -an accumulator: Function -a combiner: Function
  240. 240. @JosePaumard #J8Stream Reduction So a reduction is based on 3 operations: -a constructor: Supplier -an accumulator: Function -a combiner: Function () -> new StringBuffer() ;
  241. 241. @JosePaumard #J8Stream Reduction So a reduction is based on 3 operations: -a constructor: Supplier -an accumulator: Function -a combiner: Function () -> new StringBuffer() ; (StringBuffer sb, String s) -> sb.append(s) ;
  242. 242. @JosePaumard #J8Stream Reduction So a reduction is based on 3 operations: -a constructor: Supplier -an accumulator: Function -a combiner: Function () -> new StringBuffer() ; (StringBuffer sb, String s) -> sb.append(s) ; (StringBuffer sb1, StringBuffer sb2) -> sb1.append(sb2) ;
  243. 243. @JosePaumard #J8Stream Reduction So a reduction is based on 3 operations: -a constructor: Supplier -an accumulator: Function -a combiner: Function StringBuffer::new ; StringBuffer::append ; StringBuffer::append ;
  244. 244. @JosePaumard #J8Stream Reduction: implementation Example 1: reducing in a StringBuffer List<Person> persons = ... ; StringBuffer result = persons.stream() .filter(person -> person.getAge() > 20) .map(Person::getLastName) .collect( StringBuffer::new, // constructor StringBuffer::append, // accumulator StringBuffer::append // combiner ) ;
  245. 245. @JosePaumard #J8Stream Reduction: collectors Example 1: using a Collectors List<Person> persons = ... ; String result = persons.stream() .filter(person -> person.getAge() > 20) .map(Person::getLastName) .collect( Collectors.joining() ) ;
  246. 246. @JosePaumard #J8Stream Reduction: collectors Collecting in a String List<Person> persons = ... ; String result = persons.stream() .filter(person -> person.getAge() > 20) .map(Person::getLastName) .collect( Collectors.joining(", ") ) ;
  247. 247. @JosePaumard #J8Stream Reduction: collectors Collecting in a String List<Person> persons = ... ; String result = persons.stream() .filter(person -> person.getAge() > 20) .map(Person::getLastName) .collect( Collectors.joining(", ", "{", "}") ) ;
  248. 248. @JosePaumard #J8Stream Reduction Example 2: -a constructor: Supplier -an accumulator: Function -a combiner: Function () -> new ArrayList() ; (list, element) -> list.add(element) ; (list1, list2) -> list1.addAll(list2) ;
  249. 249. @JosePaumard #J8Stream Reduction Example 2: -a constructor: Supplier -an accumulator: Function -a combiner: Function ArrayList::new ; Collection::add ; Collection::allAll ;
  250. 250. @JosePaumard #J8Stream Reduction: implementation Example 2: reduction in a List List<Person> persons = ... ; ArrayList<String> names = persons.stream() .filter(person -> person.getAge() > 20) .map(Person::getLastName) .collect( ArrayList::new, // constructor Collection::add, // accumulator Collection::addAll // combiner ) ;
  251. 251. @JosePaumard #J8Stream Reduction: collectors Example 2: reduction in a List List<Person> persons = ... ; List<String> result = persons.stream() .filter(person -> person.getAge() > 20) .map(Person::getLastName) .collect( Collectors.toList() ) ;
  252. 252. @JosePaumard #J8Stream Reduction: implementation Example 3: reduction in a Set List<Person> persons = ... ; HashSet<String> names = persons.stream() .filter(person -> person.getAge() > 20) .map(Person::getLastName) .collect( HashSet::new, // constructor Collection::add, // accumulator Collection::addAll // combiner ) ;
  253. 253. @JosePaumard #J8Stream Reduction: collectors Example 3: reduction in a Set List<Person> persons = ... ; Set<String> result = persons.stream() .filter(person -> person.getAge() > 20) .map(Person::getLastName) .collect( Collectors.toSet() ) ;
  254. 254. @JosePaumard #J8Stream Reduction: collectors Example 4: reduction in a given collection List<Person> persons = ... ; TreeSet<String> result = persons.stream() .filter(person -> person.getAge() > 20) .map(Person::getLastName) .collect( Collectors.toCollection(TreeSet::new) ) ;
  255. 255. @JosePaumard #J8Stream Collectors Collectors class: 33 static methods An amazing toolbox!
  256. 256. @JosePaumard #J8Stream Collectors: groupingBy HashMap: age / list of the people Map<Integer, List<Person>> result = persons.stream() .collect( Collectors.groupingBy(Person::getAge) ) ;
  257. 257. @JosePaumard #J8Stream Collectors: groupingBy HashMap: age / # of people Map<Integer, Long> result = persons.stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.counting() // « downstream collector » ) ) ;
  258. 258. @JosePaumard #J8Stream Collectors: groupingBy HashMap: age / list of the names Map<Integer, List<String>> result = persons.stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.mapping( // Person::getLastName // downstream collector ) // ) ) ;
  259. 259. @JosePaumard #J8Stream Collectors: groupingBy HashMap: age / names joined in a single String Map<Integer, String> result = persons.stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.mapping( // 1st downstream collector Person::getLastName Collectors.joining(", ") // 2nd downstream collector ) ) ) ;
  260. 260. @JosePaumard #J8Stream Collectors: groupingBy HashMap: age / names sorted alphabetically Map<Integer, TreeSet<String>> result = persons.stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.mapping( Person::getLastName Collectors.toCollection(TreeSet::new) ) ) ) ;
  261. 261. @JosePaumard #J8Stream Collectors: groupingBy HashMap: the same, sorted by age TreeMap<Integer, TreeSet<String>> result = persons.stream() .collect( Collectors.groupingBy( Person::getAge, TreeMap::new, Collectors.mapping( Person::getLastName Collectors.toCollection(TreeSet::new) ) ) ) ;
  262. 262. @JosePaumard #J8Stream Wrap-up Stream + Collectors = New tools for data processing (map / filter / reduce) 1)lazy execution 2)parallelism Live coding to come!
  263. 263. @JosePaumard #J8Stream Wrap-up More to come: -use cases -live coding!
  264. 264. @JosePaumard Coffee time ! #Stream8
  265. 265. Java 8 Streams & Collectors Patterns, performance, parallelization @JosePaumard
  266. 266. Questions ? #J8Stream @JosePaumard
  267. 267. « movies and actors » https://github.com/JosePaumard/jdk8-lambda-tour http://introcs.cs.princeton.edu/java/data/
  268. 268. @JosePaumard #J8Stream Movies and actors File: « movies-mpaa.txt » With 14k movies from 1916 to 2004 With: -the title of the movie -the release year -the list of the actors (170k)
  269. 269. @JosePaumard #J8Stream Greatest release year 1st question: which year saw the most movies?
  270. 270. @JosePaumard #J8Stream Greatest release year 1st question: which year saw the most movies? 1st step: we can build a hashmap -the keys are the release year -the values the # of movies in that year
  271. 271. @JosePaumard #J8Stream Greatest release year 1st question: which year saw the most movies? 1st step: we can build a hashmap -the keys are the release year -the values the # of movies in that year 2nd step: get the key value pair with the greatest value
  272. 272. @JosePaumard #J8Stream Greatest release year Live coding
  273. 273. @JosePaumard #J8Stream Greatest release year 1st question: which year saw the most movies? Solution: map / reduce
  274. 274. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor?
  275. 275. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? Once again, we can build a hashmap: -the keys are the actors -the values are the # of movies
  276. 276. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? Let us build the set of all the actors Set<Actor> actors = movies.stream() .flatMap(movie -> movie.actors().stream()) .collect(Collector.toSet()) ;
  277. 277. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream() .collect( ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  278. 278. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream() .collect( Collectors.toMap( ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  279. 279. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream() .collect( Collectors.toMap( actor -> actor, ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  280. 280. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream() .collect( Collectors.toMap( Function.identity(), ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  281. 281. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream() .collect( Collectors.toMap( Function.identity(), actor -> movies.stream() .filter(movie -> movie.actors().contains(actor)) .count() ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  282. 282. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream().parallel() // T = 40s  .collect( Collectors.toMap( Function.identity(), actor -> movies.stream() .filter(movie -> movie.actors().contains(actor)) .count() ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  283. 283. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream().parallel() // 170k .collect( Collectors.toMap( Function.identity(), actor -> movies.stream() // 14k 2,4G!! .filter(movie -> movie.actors().contains(actor)) .count() ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  284. 284. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? Set<Actor> actors = movies.stream() .flatMap(movie -> movie.actors().stream()) // stream of actors .collect(Collector.toSet()) ;
  285. 285. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? And in this stream, if an actor played in 2 movies, she appears twice Set<Actor> actors = movies.stream() .flatMap(movie -> movie.actors().stream()) // stream of actors .collect(Collector.toSet()) ;
  286. 286. @JosePaumard #J8Stream Most seen actor Live coding
  287. 287. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? Answer: Frank Welker
  288. 288. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? Answer: Frank Welker … and in fact he’s not really the most « seen » actor
  289. 289. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? Answer: Frank Welker
  290. 290. @JosePaumard #J8Stream Most seen actor 2nd question: most seen heard actor? Answer: Frank Welker
  291. 291. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year?
  292. 292. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year? So it is a hashmap in which: -the keys are the actors -the values are other hashmaps
  293. 293. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year? So it is a hashmap in which: -the keys are the actors -the values are other hashmaps -in which keys are the release years -and the values the # of movies → AtomicLong
  294. 294. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year? movies.stream() .flatMap(movie -> movie.actors().stream()) .collect( Collectors.groupingBy( // build a Map<year, ...> movie -> movie.releaserYear(), // build a Map<Actor, # of movies> ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  295. 295. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year? movies.stream() .flatMap(movie -> movie.actors().stream()) .collect( Collectors.groupingBy( // build a Map<year, ...> movie -> movie.releaserYear(), // build a Map<Actor, # of movies> -> custom DS Collector ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  296. 296. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year? So it is a hashmap in which: -the keys are the actors -the values are other hashmaps -in which keys are the release years -and the values the # of movies → AtomicLong And we want the max by the # of movies
  297. 297. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year? We need 3 things to build a collector -a constructor for the resulting container -an accumulator to add an element to the container -a combiner that merges two partially filled containers
  298. 298. @JosePaumard #J8Stream Most seen actor in a year Live coding
  299. 299. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year?
  300. 300. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year? Answer: Phil Hawn, in 1999 played in 24 movies
  301. 301. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year? Answer: Phil Hawn, in 1999 played in 24 movies
  302. 302. « Shakespeare plays Scrabble » https://github.com/JosePaumard/jdk8-lambda-tour http://introcs.cs.princeton.edu/java/data/
  303. 303. @JosePaumard #J8Stream Scrabble Two files: -OSPD = official personnal Scrabble dictionary -The words used by Shakespeare
  304. 304. @JosePaumard #J8Stream Scrabble Two files: -OSPD = official personnal Scrabble dictionary -The words used by Shakespeare -And some documentation (Wikipedia) private static final int [] scrabbleENScore = { // a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z 1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10} ;
  305. 305. @JosePaumard #J8Stream Scrabble: score of a word 1st question: how to compute the score of a word H E L L O 4 1 1 1 1 // from the scrabbleENScore array
  306. 306. @JosePaumard #J8Stream Scrabble: score of a word 1st question: how to compute the score of a word H E L L O 4 1 1 1 1 // from the scrabbleENScore array SUM = 8
  307. 307. @JosePaumard #J8Stream Scrabble: score of a word 1st question: how to compute the score of a word H E L L O // this is a stream of the letters of the word HELLO 4 1 1 1 1 SUM = 8
  308. 308. @JosePaumard #J8Stream Scrabble: score of a word 1st question: how to compute the score of a word H E L L O // this is a stream of the letters of the word HELLO 4 1 1 1 1 // mapping : letter -> score of the letter SUM = 8
  309. 309. @JosePaumard #J8Stream Scrabble: score of a word 1st question: how to compute the score of a word H E L L O // this is a stream of the letters of the word HELLO 4 1 1 1 1 // mapping : letter -> score of the letter SUM // reduction : sum = 8
  310. 310. @JosePaumard #J8Stream Scrabble: score of a word Live coding
  311. 311. @JosePaumard #J8Stream Scrabble: score of a word 1st question: how to compute the score of a word = map / reduce
  312. 312. @JosePaumard #J8Stream Scrabble: score of Shakespeare 2nd question: compute the best word of Shakespeare
  313. 313. @JosePaumard #J8Stream Scrabble: score of Shakespeare 2nd question: compute the best word of Shakespeare 1)Histogram: score of the words / list of the words
  314. 314. @JosePaumard #J8Stream Scrabble: score of Shakespeare 2nd question: compute the best word of Shakespeare 1)Histogram: score of the words / list of the words 2)Max by key value
  315. 315. @JosePaumard #J8Stream Scrabble: score of Shakespeare 2nd question: compute the best word of Shakespeare 1)Histogram: score of the words / list of the words HashMap, Collectors.groupingBy() 2)Max by key value
  316. 316. @JosePaumard #J8Stream Scrabble: score of Shakespeare 2nd question: compute the best word of Shakespeare 1)Histogram: score of the words / list of the words HashMap, Collectors.groupingBy() 2)Max by key value Shouldnt be too hard
  317. 317. @JosePaumard #J8Stream Scrabble: score of Shakespeare Live coding
  318. 318. @JosePaumard #J8Stream Scrabble: score of Shakespeare 3rd question: filter out the wrong words We need to add a filtering step
  319. 319. @JosePaumard #J8Stream Scrabble: score of Shakespeare Live coding
  320. 320. @JosePaumard #J8Stream Scrabble: score of Shakespeare 3rd question: filter out the wrong words Solution: map / filter / reduce
  321. 321. @JosePaumard #J8Stream Scrabble: score of Shakespeare Question: can one really write this word?
  322. 322. @JosePaumard #J8Stream Scrabble: score of Shakespeare Question: can one really write this word? private static final int [] scrabbleENDistribution = { // a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z 9, 2, 2, 1, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1} ;
  323. 323. @JosePaumard #J8Stream Scrabble: score of Shakespeare Answer: no… private static final int [] scrabbleENDistribution = { // a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z 9, 2, 2, 1, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1} ;
  324. 324. @JosePaumard #J8Stream Filtering V2 4th question: how to check if I have the available letters? private static final int [] scrabbleENDistribution = { // a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z 9, 2, 2, 1, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1} ;
  325. 325. @JosePaumard #J8Stream Filtering V2 4th question: how to check if I have the available letters? 1 1 2 2 1 1 needed letters
  326. 326. @JosePaumard #J8Stream Filtering V2 4th question: how to check if I have the available letters? 1 1 2 2 1 1 1 4 9 1 6 3 needed letters available letters
  327. 327. @JosePaumard #J8Stream Filtering V2 4th question: how to check if I have the available letters? I need a allMatch() reducer! 1 1 2 2 1 1 1 4 9 1 6 3 needed letters available letters
  328. 328. @JosePaumard #J8Stream Filtering V2 Live coding
  329. 329. @JosePaumard #J8Stream Filtering V2 4th question: how to check if I have the available letters? Solution: map / filter / reduce
  330. 330. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: and what about using blanks?
  331. 331. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: and what about using blanks? private static final int [] scrabbleENDistribution = { // a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z 9, 2, 2, 1, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1} ;
  332. 332. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: and what about using blanks? private static final int [] scrabbleENDistribution = { // a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z 9, 2, 2, 1, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1} ;
  333. 333. @JosePaumard #J8Stream Scrabble: use of blanks It has 2 impacts: -on the filtering of the words -on the computation of the score
  334. 334. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: how to compute the score? 1 1 2 2 1 1
  335. 335. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: how to compute the score? 1 1 2 2 1 1 1 4 9 1 6 3
  336. 336. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: how to compute the score? 1 1 2 2 1 1 1 4 9 1 6 3 10 1 2 10 1 2 → 26
  337. 337. @JosePaumard #J8Stream Scrabble: use of blanks Live coding
  338. 338. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: how to compute the score? Solution: map / filter / reduce
  339. 339. @JosePaumard #J8Stream Scrabble: use of blanks 6th question: how many blanks do we need? 1 1 2 2 1 1
  340. 340. @JosePaumard #J8Stream Scrabble: use of blanks 6th question: how many blanks do we need? 1 1 2 2 1 1 1 4 9 1 6 3
  341. 341. @JosePaumard #J8Stream Scrabble: use of blanks 6th question: how many blanks do we need? 1 1 2 2 1 1 1 4 9 1 6 3 0 -3 -7 +1 -5 -2
  342. 342. @JosePaumard #J8Stream Scrabble: use of blanks 6th question: how many blanks do we need? 1 1 2 2 1 1 1 4 9 1 6 3 0 0 0 +1 0 0 → 1
  343. 343. @JosePaumard #J8Stream Scrabble: use of blanks Live coding
  344. 344. @JosePaumard #J8Stream Use of a blank 6th question: how many blanks do we need? Solution: map / reduce
  345. 345. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score?
  346. 346. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score?
  347. 347. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score?
  348. 348. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? 6 solutions to put the word: -right square = 3 last letters -left square= 3 first letters
  349. 349. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? 6 solutions to put the word: -right square = 3 last letters -left square= 3 first letters If the word is long enough (7 letters)!
  350. 350. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? So we need to take a max, on which set? word.chars().skip(4) // 1st stream word.chars().limit(Integer.max(0, word.length() - 4)) // 2nd stream
  351. 351. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? IntStream.concat( word.chars().skip(4), word.chars().limit(Integer.max(0, word.length() - 4)) ) .map(scrabbleENScore) .max()
  352. 352. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? Problem: concat does not parallel well IntStream.concat( word.chars().skip(4), word.chars().limit(Integer.max(0, word.length() - 4)) ) .map(scrabbleENScore) .max()
  353. 353. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? Stream.of( word.chars().skip(4), word.chars().limit(Integer.max(0, word.length() - 4)) ) // returns a Stream of Stream!
  354. 354. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? Stream.of( word.chars().skip(4), word.chars().limit(Integer.max(0, word.length() - 4)) ) .flatMapToInt(Function.identity()) // chars() is an IntStream .map(scrabbleENScore) .max() // we have an IntStream!
  355. 355. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? What should we do with this Optional? Stream.of( word.chars().skip(4), word.chars().limit(Integer.max(0, word.length() - 4)) ) .flatMapToInt(Function.identity()) // chars() is an IntStream .map(scrabbleENScore) .max() // we have an IntStream!
  356. 356. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? … that can be empty! Stream.of( word.chars().skip(4), word.chars().limit(Integer.max(0, word.length() - 4)) ) .flatMapToInt(Function.identity()) // chars() is an IntStream .map(scrabbleENScore) .max() // we have an IntStream!
  357. 357. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score? … that can be empty! Stream.of( word.chars().skip(4), word.chars().limit(Integer.max(0, word.length() - 4)) ) .flatMapToInt(Function.identity()) // chars() is an IntStream .map(scrabbleENScore) .max() // we have an IntStream! .orElse(0) ;
  358. 358. @JosePaumard #J8Stream Scrabble: and what about the board? Live coding
  359. 359. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: can we take the Double letter score? Solution: map / reduce
  360. 360. https://github.com/JosePaumard/jdk8-lambda-tour
  361. 361. @JosePaumard #J8Stream Conclusion Streams + Collectors = no need to use the Iterator pattern any more
  362. 362. @JosePaumard #J8Stream Conclusion Streams + Collectors = no need to use the Iterator pattern any more Combined with lambdas = new way of writing data processing and applications in Java
  363. 363. @JosePaumard #J8Stream Conclusion Streams + Collectors = no need to use the Iterator pattern any more Combined with lambdas = new way of writing data processing in Java -writing code -architecture
  364. 364. @JosePaumard #J8Stream Conclusion Some books:
  365. 365. Thank you! @JosePaumard #Stream8
  366. 366. @JosePaumard #Stream8

×