SlideShare une entreprise Scribd logo
1  sur  373
Télécharger pour lire hors ligne
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: live coding! 
-Movies & actors 
-Shakespeare
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, Stream<T>> { 
// ... 
}
@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>> { 
// ... 
}
@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 also small ones
@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 CPU
@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
@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 Collection to be a Stream!
@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!
@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…
@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
@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
@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 hold any data
@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
@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 »
@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
@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<Person> stream = persons.stream() ;
@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)) ;
@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) ;
@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
@JosePaumard 
#J8Stream 
Operation: forEach() 
First operation: forEach() 
forEach(): takes a Consumer<T> as a parameter 
@FunctionalInterface public interface Consumer<T> { void accept(T t) ; }
@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) ; 
}
@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 Object do not count)
@JosePaumard 
#J8Stream 
Functional interface 
Definition: 
an interface with only one abstract method 
(methods from Object do not count) 
(default & static methods do not count)
@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
@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
@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); }; 
} 
}
@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); }; 
} 
}
@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 without breaking the old implementations
@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
@JosePaumard 
#J8Stream 
Collection.stream() 
public interface Collection<E> { 
default Stream<E> stream() { 
return StreamSupport.stream(spliterator(), false); 
} 
}
@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); 
} 
}
@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); }; 
} 
}
@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) ;
@JosePaumard 
#J8Stream 
Back to the Consumer interface 
List<String> list = new ArrayList<>() ; 
Consumer<String> c1 = list::add ; 
Consumer<String> c2 = System.out::println ;
@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
@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?
@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?
@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!
@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)) ;
@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 !
@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 = list.stream() ; 
Stream<Person> filtered = 
stream.filter(person -> person.getAge() > 20) ;
@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) ;
@JosePaumard 
#J8Stream 
Interface Predicate 
Another functional interface 
@FunctionalInterface public interface Predicate<T> { boolean test(T t) ; }
@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() { ... } 
}
@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) ; 
}
@JosePaumard 
#J8Stream 
Interface Predicate: patterns 
Predicate<Integer> p1 = i -> i > 20 ; 
Predicate<Integer> p2 = i -> i < 30 ; 
Predicate<Integer> p3 = i -> i == 0 ;
@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
@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
@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) { ... } 
}
@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(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) ; 
}
@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 ; 
}
@JosePaumard 
#J8Stream 
Interface Predicate 
We also have: 
@FunctionalInterface 
public interface BiPredicate<T, U> { 
boolean test(T t, U u); 
}
@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) ;
@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) ;
@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) ;
@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) ;
@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) ;
@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) ;
@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) ;
@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) ;
@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) ;
@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
@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
@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
@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…
@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 !
@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 !
@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 !
@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 notion of lazyness / intermediate call
@JosePaumard 
#J8Stream 
Let us carry on 
And see the mapping operation
@JosePaumard 
#J8Stream 
Mapping 
Mapping operation 
List<Person> list = ... ; 
Stream<Person> stream = list.stream() ; 
Stream<String> names = 
stream.map(person -> person.getName()) ;
@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()) ;
@JosePaumard 
#J8Stream 
Interface Function 
The map() method takes a Function: 
@FunctionalInterface 
public interface Function<T, R> { 
R apply(T t) ; 
}
@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) ; 
}
@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) ; 
}
@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) ; 
}
@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 ; 
} 
}
@JosePaumard 
#J8Stream 
Other functions 
There are special types of functions: 
@FunctionalInterface 
public interface UnaryOperator<T> extends Function<T, T> { 
}
@JosePaumard 
#J8Stream 
Other functions 
There are special types of functions: 
@FunctionalInterface 
public interface BiFunction<T, U, R> { 
R apply(T t, U u); 
}
@JosePaumard 
#J8Stream 
Other functions 
There are special types of functions: 
@FunctionalInterface 
public interface BinaryOperator<T> extends BiFunction<T, T, T> { 
}
@JosePaumard 
#J8Stream 
What do we have so far? 
We saw: 
-forEach(Consumer) 
-peek(Consumer) 
-filter(Predicate) 
-map(Function)
@JosePaumard 
#J8Stream 
Let us carry on 
Method flatMap()
@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) ;
@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>>
@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>>
@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();
@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>
@JosePaumard 
#J8Stream 
Method flatMap() 
flatMap() = flattens a Stream 
Signature: 
<R> Stream<R> flatMap(Function<T, Stream<R>> mapper) ;
@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) ;
@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
@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() ; 
Integer sum = 
stream.reduce(0, (age1, age2) -> age1 + age2) ;
@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) ;
@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) ;
@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) ;
@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) ;
@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) ;
@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
@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 course we do not use such reductions…
@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) ;
@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) ;
@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) -> i1 > i2 ? i1 : i2 ;
@JosePaumard 
#J8Stream 
Reduction 
Associative, or not associative? 
red1 = (i1, i2) -> i1 + i2 ;  
red2 = (i1, i2) -> i1 > i2 ? i1 : i2 ;  
red3 = (i1, i2) -> i1*i2 ;
@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 ;
@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 ;
@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 ;
@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 ; 
@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) ;
@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) ;
@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
@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
@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
@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
@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 identity element, thus no default value
@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
@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()) ;
@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 { 
... 
}
@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 { 
... 
}
@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
@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
@JosePaumard 
#J8Stream 
Optional: more patterns 
An Optional can be seen as a special Stream with zero or one element 
void ifPresent(Consumer<T> consumer) ;
@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) ;
@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) ;
@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) ;
@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)) ; 
} 
}
@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]
@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]
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
Function<Double, Optional<Double>> f = 
d -> NewMath.inv(d) // Optional<Double> 
.flatMap(d -> NewMath.sqrt(d))// Optional<Double>
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
Function<Double, Optional<Double>> f = 
d -> NewMath.inv(d) // Optional<Double> 
.flatMap(NewMath::sqrt); // Optional<Double>
@JosePaumard 
#J8Stream 
Optional: new patterns sighted! 
d -> NewMath.inv(d) // Optional<Double> 
.flatMap(NewMath::sqrt) // Optional<Double> 
.map(Stream::of) // Optional<Stream<Double>>
@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>
@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>
@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>
@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()) ;
@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) ;
@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) ;
@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!)
@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
@JosePaumard 
#J8Stream 
Terminal operation 
Example 
List<Person> persons = ... ; 
... = 
persons.map(person -> person.getAge()) // Stream<Integer> 
.filter(age -> age > 20) // Stream<Integer> 
.min(Comparator.naturalOrder()) ;
@JosePaumard 
#J8Stream 
Terminal operation 
Example 
List<Person> persons = ... ; 
... = 
persons.map(Person::getAge) // Stream<Integer> 
.filter(age -> age > 20) // Stream<Integer> 
.min(Comparator.naturalOrder()) ;
@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
@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
@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
@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
@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
@JosePaumard 
#J8Stream 
What is a Stream? 
Pipeline approach: 
1)we define the operations 
2)we trigger the computations by calling a terminal operation
@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
@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); }
@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) ; 
}
@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); }
@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); 
}
@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);
@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);
@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();
@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();
@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(); 
}
@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; 
}
@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; 
}
@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
@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 
-
@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()) ;
@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()) ;
@JosePaumard 
#J8Stream 
Stream implementation 
Complex! 
Two parts: 
1)algorithms are in ReferencePipeline 
2)data access: Spliterator, can be overriden
@JosePaumard 
#J8Stream 
A few words on Comparator 
We wrote: 
// Comparator interface 
Comparator cmp = Comparator.naturalOrder() ;
@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; 
}
@JosePaumard 
#J8Stream 
A few words on Comparator 
// Comparators class 
enum NaturalOrderComparator 
implements Comparator<Comparable<Object>> { 
INSTANCE; 
}
@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; } }
@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(); 
} 
}
@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) ;
@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)); 
}
@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)); 
}
@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)); 
}
@JosePaumard 
#J8Stream 
A few words on Comparator 
Method thenComparing() 
// Comparator interface 
default 
<U> Comparator<T> 
thenComparing(Function<T, U> keyExtractor) { 
return thenComparing(comparing(keyExtractor)); 
}
@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)); 
}
@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); 
}; 
}
@JosePaumard 
#J8Stream 
What do we have so far? 
API Stream 
-intermediate operations 
-terminal operations 
-implementation built on 2 classes
@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) ;
@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) ;
@JosePaumard 
#J8Stream 
Stateless / stateful operations 
This code: 
ArrayList<Person> persons = ... ; 
List<String> names = 
persons.map(Person::getLastName) 
.collect(Collectors.toList()) ;
@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()) ;
@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()) ;
@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()) ;
@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
@JosePaumard 
#J8Stream 
Stream & performance 
Two elements: 
-lazy processing, on one pass over the data 
-parallel processing
@JosePaumard 
#J8Stream 
Stream & performance 
Two elements: 
-lazy processing, on one pass over the data 
-parallel processing 
Stream<T> versus IntStream, LongStream, DoubleStream
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again: 
ArrayList<Person> persons = ... ; 
persons.stream() 
.map(Person::getAge) 
.filter(age -> age > 20) 
.sum() ;
@JosePaumard 
#J8Stream 
Stream & performance 
Let see this example again: 
ArrayList<Person> persons = ... ; 
persons.stream() // Stream<Person> 
.map(Person::getAge) 
.filter(age -> age > 20) 
.sum() ;
@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() ;
@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() ;
@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>
@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() ;
@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() ;
@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() ;
@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() ;
@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() ;
@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() ;
@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() ;
@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() ;
@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() ;
@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() ;
@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
@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) ;
@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() ;
@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 seen in a more general sense
@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 to the result is… adding
@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 »
@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 
-adding an element to that container
@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
@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
@JosePaumard 
#J8Stream 
Reduction 
So a reduction is based on 3 operations: 
-a constructor: Supplier 
-an accumulator: Function 
-a combiner: Function
@JosePaumard 
#J8Stream 
Reduction 
So a reduction is based on 3 operations: 
-a constructor: Supplier 
-an accumulator: Function 
-a combiner: Function 
() -> new StringBuffer() ;
@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) ;
@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) ;
@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 ;
@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 ) ;
@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() ) ;
@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(", ") ) ;
@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(", ", "{", "}") ) ;
@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) ;
@JosePaumard 
#J8Stream 
Reduction 
Example 2: 
-a constructor: Supplier 
-an accumulator: Function 
-a combiner: Function 
ArrayList::new ; 
Collection::add ; 
Collection::allAll ;
@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 ) ;
@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() ) ;
@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 ) ;
@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() ) ;
@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) ) ;
@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 = 
persons.stream() 
.collect( 
Collectors.groupingBy(Person::getAge) 
) ;
@JosePaumard 
#J8Stream 
Collectors: groupingBy 
HashMap: age / # of people 
Map<Integer, Long> result = 
persons.stream() 
.collect( 
Collectors.groupingBy( 
Person::getAge, 
Collectors.counting() // « downstream collector » 
) 
) ;
@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 
) // 
) 
) ;
@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 
) 
) 
) ;
@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) 
) 
) 
) ;
@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) 
) 
) 
) ;
@JosePaumard 
#J8Stream 
Wrap-up 
Stream + Collectors = 
New tools for data processing (map / filter / reduce) 
1)lazy execution 
2)parallelism 
Live coding to come!
@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 title of the movie 
-the release year 
-the list of the actors (170k)
@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 hashmap 
-the keys are the release year 
-the values the # of movies in that year
@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
@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 are the actors 
-the values are the # of movies
@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()) ;
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream() .collect( ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream() 
.collect( 
Collectors.toMap( 
) 
) 
.entrySet().stream() 
.max(Map.Entry.comparingByValue()).get() ;
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream() .collect( Collectors.toMap( actor -> actor, ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
@JosePaumard 
#J8Stream 
Most seen actor 
2nd question: most seen actor? 
actors.stream() 
.collect( 
Collectors.toMap( 
Function.identity(), 
) 
) 
.entrySet().stream() 
.max(Map.Entry.comparingByValue()).get() ;
@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() ;
@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() ;
@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() ;
@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()) ;
@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()) ;
@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 really the most « seen » actor
@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 which: 
-the keys are the actors 
-the values are other hashmaps
@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
@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() ;
@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() ;
@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
@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
@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 1999 played in 24 movies
@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
« 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 Shakespeare
@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} ;
@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
@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
@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
@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
@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
@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: score of the words / list of the words
@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
@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
@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
@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 filtering step
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
Live coding
@JosePaumard 
#J8Stream 
Scrabble: score of Shakespeare 
3rd question: filter out the wrong words 
Solution: map / filter / reduce
@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 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} ;
@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} ;
@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} ;
@JosePaumard 
#J8Stream 
Filtering V2 
4th question: how to check if I have the available letters? 
1 
1 
2 
2 
1 
1 
needed letters
@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
@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
@JosePaumard 
#J8Stream 
Filtering V2 
Live coding
@JosePaumard 
#J8Stream 
Filtering V2 
4th question: how to check if I have the available letters? 
Solution: map / filter / reduce
@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 [] 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} ;
@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} ;
@JosePaumard 
#J8Stream 
Scrabble: use of blanks 
It has 2 impacts: 
-on the filtering of the words 
-on the computation of the score
@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 
3
@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
@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 
6 
3
@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
@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
@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 solutions to put the word: 
-right square = 3 last letters 
-left square= 3 first letters
@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)!
@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
@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()
@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()
@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!
@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!
@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!
@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!
@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) ;
@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: map / reduce
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 lambdas = new way of writing data processing and applications in Java
@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
@JosePaumard 
#J8Stream 
Conclusion 
Some books:
Thank you! 
@JosePaumard 
#Stream8
@JosePaumard 
#Stream8

Contenu connexe

Tendances

Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot IntroductionJeevesh Pandey
 
L'API Collector dans tous ses états
L'API Collector dans tous ses étatsL'API Collector dans tous ses états
L'API Collector dans tous ses étatsJosé Paumard
 
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
An Introduction to JUnit 5 and how to use it with Spring boot tests and MockitoAn Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockitoshaunthomas999
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJosé Paumard
 
Building RESTful applications using Spring MVC
Building RESTful applications using Spring MVCBuilding RESTful applications using Spring MVC
Building RESTful applications using Spring MVCIndicThreads
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications JavaAntoine Rey
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with SpringJoshua Long
 
How to go about testing in React?
How to go about testing in React? How to go about testing in React?
How to go about testing in React? Lisa Gagarina
 
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門tamtam180
 
Spring boot - an introduction
Spring boot - an introductionSpring boot - an introduction
Spring boot - an introductionJonathan Holloway
 
Monitoring using Prometheus and Grafana
Monitoring using Prometheus and GrafanaMonitoring using Prometheus and Grafana
Monitoring using Prometheus and GrafanaArvind Kumar G.S
 
Introduction to Testcontainers
Introduction to TestcontainersIntroduction to Testcontainers
Introduction to TestcontainersVMware Tanzu
 
Nestjs MasterClass Slides
Nestjs MasterClass SlidesNestjs MasterClass Slides
Nestjs MasterClass SlidesNir Kaufman
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOPDzmitry Naskou
 

Tendances (20)

Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot Introduction
 
L'API Collector dans tous ses états
L'API Collector dans tous ses étatsL'API Collector dans tous ses états
L'API Collector dans tous ses états
 
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
An Introduction to JUnit 5 and how to use it with Spring boot tests and MockitoAn Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
 
Spring data jpa
Spring data jpaSpring data jpa
Spring data jpa
 
Building RESTful applications using Spring MVC
Building RESTful applications using Spring MVCBuilding RESTful applications using Spring MVC
Building RESTful applications using Spring MVC
 
Airflow and supervisor
Airflow and supervisorAirflow and supervisor
Airflow and supervisor
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications Java
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 
How to go about testing in React?
How to go about testing in React? How to go about testing in React?
How to go about testing in React?
 
Spring Boot Tutorial
Spring Boot TutorialSpring Boot Tutorial
Spring Boot Tutorial
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
 
Spring boot - an introduction
Spring boot - an introductionSpring boot - an introduction
Spring boot - an introduction
 
Monitoring using Prometheus and Grafana
Monitoring using Prometheus and GrafanaMonitoring using Prometheus and Grafana
Monitoring using Prometheus and Grafana
 
Introduction to Testcontainers
Introduction to TestcontainersIntroduction to Testcontainers
Introduction to Testcontainers
 
Nestjs MasterClass Slides
Nestjs MasterClass SlidesNestjs MasterClass Slides
Nestjs MasterClass Slides
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOP
 
An Introduction To REST API
An Introduction To REST APIAn Introduction To REST API
An Introduction To REST API
 

En vedette

50 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 850 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 8José Paumard
 
Autumn collection JavaOne 2014
Autumn collection JavaOne 2014Autumn collection JavaOne 2014
Autumn collection JavaOne 2014José Paumard
 
50 new things you can do with java 8
50 new things you can do with java 850 new things you can do with java 8
50 new things you can do with java 8José Paumard
 
Les Streams sont parmi nous
Les Streams sont parmi nousLes Streams sont parmi nous
Les Streams sont parmi nousJosé Paumard
 
JDK 8, lambdas, streams, collectors - Bretagne Tour
JDK 8, lambdas, streams, collectors - Bretagne TourJDK 8, lambdas, streams, collectors - Bretagne Tour
JDK 8, lambdas, streams, collectors - Bretagne TourJosé Paumard
 
API Asynchrones en Java 8
API Asynchrones en Java 8API Asynchrones en Java 8
API Asynchrones en Java 8José Paumard
 
Business intelligence v0.3
Business intelligence v0.3Business intelligence v0.3
Business intelligence v0.3Luca Mauri
 
JAX RS and CDI bike the reactive bridge
JAX RS and CDI bike the reactive bridgeJAX RS and CDI bike the reactive bridge
JAX RS and CDI bike the reactive bridgeJosé Paumard
 
HTTP2 : ce qui va changer par Julien Landuré
HTTP2 : ce qui va changer par Julien LanduréHTTP2 : ce qui va changer par Julien Landuré
HTTP2 : ce qui va changer par Julien LanduréZenika
 
HTTP/2 Changes Everything
HTTP/2 Changes EverythingHTTP/2 Changes Everything
HTTP/2 Changes EverythingLori MacVittie
 
NightClazz Java 8 Decouverte
NightClazz Java 8 DecouverteNightClazz Java 8 Decouverte
NightClazz Java 8 DecouverteZenika
 
NightClazz Build Tools & Continuous Delivery Avancé
NightClazz Build Tools & Continuous Delivery AvancéNightClazz Build Tools & Continuous Delivery Avancé
NightClazz Build Tools & Continuous Delivery AvancéZenika
 
Azure Business rules v0.3
Azure Business rules v0.3Azure Business rules v0.3
Azure Business rules v0.3Luca Mauri
 
The Case for HTTP/2
The Case for HTTP/2The Case for HTTP/2
The Case for HTTP/2Andy Davies
 
Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017Jean-Michel Doudoux
 
Http2 les impacts dans le web
Http2 les impacts dans le webHttp2 les impacts dans le web
Http2 les impacts dans le webneuros
 
Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Jean-Michel Doudoux
 
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"UX STRAT
 

En vedette (20)

50 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 850 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 8
 
Autumn collection JavaOne 2014
Autumn collection JavaOne 2014Autumn collection JavaOne 2014
Autumn collection JavaOne 2014
 
50 new things you can do with java 8
50 new things you can do with java 850 new things you can do with java 8
50 new things you can do with java 8
 
Les Streams sont parmi nous
Les Streams sont parmi nousLes Streams sont parmi nous
Les Streams sont parmi nous
 
JDK 8, lambdas, streams, collectors - Bretagne Tour
JDK 8, lambdas, streams, collectors - Bretagne TourJDK 8, lambdas, streams, collectors - Bretagne Tour
JDK 8, lambdas, streams, collectors - Bretagne Tour
 
API Asynchrones en Java 8
API Asynchrones en Java 8API Asynchrones en Java 8
API Asynchrones en Java 8
 
Business intelligence v0.3
Business intelligence v0.3Business intelligence v0.3
Business intelligence v0.3
 
JAX RS and CDI bike the reactive bridge
JAX RS and CDI bike the reactive bridgeJAX RS and CDI bike the reactive bridge
JAX RS and CDI bike the reactive bridge
 
HTTP2 : ce qui va changer par Julien Landuré
HTTP2 : ce qui va changer par Julien LanduréHTTP2 : ce qui va changer par Julien Landuré
HTTP2 : ce qui va changer par Julien Landuré
 
HTTP/2 Changes Everything
HTTP/2 Changes EverythingHTTP/2 Changes Everything
HTTP/2 Changes Everything
 
Http2
Http2Http2
Http2
 
NightClazz Java 8 Decouverte
NightClazz Java 8 DecouverteNightClazz Java 8 Decouverte
NightClazz Java 8 Decouverte
 
NightClazz Build Tools & Continuous Delivery Avancé
NightClazz Build Tools & Continuous Delivery AvancéNightClazz Build Tools & Continuous Delivery Avancé
NightClazz Build Tools & Continuous Delivery Avancé
 
Azure Business rules v0.3
Azure Business rules v0.3Azure Business rules v0.3
Azure Business rules v0.3
 
The Case for HTTP/2
The Case for HTTP/2The Case for HTTP/2
The Case for HTTP/2
 
Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017
 
Http2 les impacts dans le web
Http2 les impacts dans le webHttp2 les impacts dans le web
Http2 les impacts dans le web
 
Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016
 
Company_Profile_Digital_1
Company_Profile_Digital_1Company_Profile_Digital_1
Company_Profile_Digital_1
 
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
 

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

Java 8 Stream API and RxJava Comparison
Java 8 Stream API and RxJava ComparisonJava 8 Stream API and RxJava Comparison
Java 8 Stream API and RxJava ComparisonJosé Paumard
 
Java 8 Streams and Rx Java Comparison
Java 8 Streams and Rx Java ComparisonJava 8 Streams and Rx Java Comparison
Java 8 Streams and Rx Java ComparisonJosé Paumard
 
Going reactive in java
Going reactive in javaGoing reactive in java
Going reactive in javaJosé Paumard
 
Java 8 - Lambdas and much more
Java 8 - Lambdas and much moreJava 8 - Lambdas and much more
Java 8 - Lambdas and much moreAlin Pandichi
 
Lambdas: Myths and Mistakes
Lambdas: Myths and MistakesLambdas: Myths and Mistakes
Lambdas: Myths and MistakesRichardWarburton
 
course slides -- powerpoint
course slides -- powerpointcourse slides -- powerpoint
course slides -- powerpointwebhostingguy
 
devLink - What's New in C# 4?
devLink - What's New in C# 4?devLink - What's New in C# 4?
devLink - What's New in C# 4?Kevin Pilch
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.David Gómez García
 
computer notes - Data Structures - 5
computer notes - Data Structures - 5computer notes - Data Structures - 5
computer notes - Data Structures - 5ecomputernotes
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Juan Pablo
 
Clean code _v2003
 Clean code _v2003 Clean code _v2003
Clean code _v2003R696
 
Jaoo - Open Social A Standard For The Social Web
Jaoo - Open Social A Standard For The Social WebJaoo - Open Social A Standard For The Social Web
Jaoo - Open Social A Standard For The Social WebPatrick Chanezon
 
Reactive clean architecture
Reactive clean architectureReactive clean architecture
Reactive clean architectureViktor Nyblom
 
Incredible Machine with Pipelines and Generators
Incredible Machine with Pipelines and GeneratorsIncredible Machine with Pipelines and Generators
Incredible Machine with Pipelines and Generatorsdantleech
 

Similaire à Java 8, Streams & Collectors, patterns, performances and parallelization (20)

Java 8 Stream API and RxJava Comparison
Java 8 Stream API and RxJava ComparisonJava 8 Stream API and RxJava Comparison
Java 8 Stream API and RxJava Comparison
 
Java 8 Streams and Rx Java Comparison
Java 8 Streams and Rx Java ComparisonJava 8 Streams and Rx Java Comparison
Java 8 Streams and Rx Java Comparison
 
Going reactive in java
Going reactive in javaGoing reactive in java
Going reactive in java
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
Java 8 new features
Java 8 new featuresJava 8 new features
Java 8 new features
 
Java 8 - Lambdas and much more
Java 8 - Lambdas and much moreJava 8 - Lambdas and much more
Java 8 - Lambdas and much more
 
Lambdas: Myths and Mistakes
Lambdas: Myths and MistakesLambdas: Myths and Mistakes
Lambdas: Myths and Mistakes
 
course slides -- powerpoint
course slides -- powerpointcourse slides -- powerpoint
course slides -- powerpoint
 
devLink - What's New in C# 4?
devLink - What's New in C# 4?devLink - What's New in C# 4?
devLink - What's New in C# 4?
 
Java8.part2
Java8.part2Java8.part2
Java8.part2
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.
 
computer notes - Data Structures - 5
computer notes - Data Structures - 5computer notes - Data Structures - 5
computer notes - Data Structures - 5
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
 
Clean code _v2003
 Clean code _v2003 Clean code _v2003
Clean code _v2003
 
Jaoo - Open Social A Standard For The Social Web
Jaoo - Open Social A Standard For The Social WebJaoo - Open Social A Standard For The Social Web
Jaoo - Open Social A Standard For The Social Web
 
Reactive clean architecture
Reactive clean architectureReactive clean architecture
Reactive clean architecture
 
Incredible Machine with Pipelines and Generators
Incredible Machine with Pipelines and GeneratorsIncredible Machine with Pipelines and Generators
Incredible Machine with Pipelines and Generators
 
Java 8 by example!
Java 8 by example!Java 8 by example!
Java 8 by example!
 

Plus de José Paumard

Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19José Paumard
 
From Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdfFrom Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdfJosé Paumard
 
The Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern MatchingThe Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern MatchingJosé Paumard
 
Designing functional and fluent API: application to some GoF patterns
Designing functional and fluent API: application to some GoF patternsDesigning functional and fluent API: application to some GoF patterns
Designing functional and fluent API: application to some GoF patternsJosé Paumard
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé Paumard
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé Paumard
 
Designing functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor PatternDesigning functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor PatternJosé Paumard
 
Construire son JDK en 10 étapes
Construire son JDK en 10 étapesConstruire son JDK en 10 étapes
Construire son JDK en 10 étapesJosé Paumard
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!José Paumard
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1José Paumard
 
Asynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowAsynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowJosé Paumard
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJosé Paumard
 
Collectors in the Wild
Collectors in the WildCollectors in the Wild
Collectors in the WildJosé Paumard
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full storyJosé Paumard
 
ArrayList et LinkedList sont dans un bateau
ArrayList et LinkedList sont dans un bateauArrayList et LinkedList sont dans un bateau
ArrayList et LinkedList sont dans un bateauJosé Paumard
 
Java SE 8 for Java EE developers
Java SE 8 for Java EE developersJava SE 8 for Java EE developers
Java SE 8 for Java EE developersJosé Paumard
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureJosé Paumard
 
Java SE 8 for Java EE developers
Java SE 8 for Java EE developersJava SE 8 for Java EE developers
Java SE 8 for Java EE developersJosé Paumard
 

Plus de José Paumard (20)

Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19
 
From Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdfFrom Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdf
 
The Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern MatchingThe Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern Matching
 
Designing functional and fluent API: application to some GoF patterns
Designing functional and fluent API: application to some GoF patternsDesigning functional and fluent API: application to some GoF patterns
Designing functional and fluent API: application to some GoF patterns
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
Designing functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor PatternDesigning functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor Pattern
 
Construire son JDK en 10 étapes
Construire son JDK en 10 étapesConstruire son JDK en 10 étapes
Construire son JDK en 10 étapes
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1
 
Asynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowAsynchronous Systems with Fn Flow
Asynchronous Systems with Fn Flow
 
Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) Bridge
 
Collectors in the Wild
Collectors in the WildCollectors in the Wild
Collectors in the Wild
 
Streams in the wild
Streams in the wildStreams in the wild
Streams in the wild
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full story
 
ArrayList et LinkedList sont dans un bateau
ArrayList et LinkedList sont dans un bateauArrayList et LinkedList sont dans un bateau
ArrayList et LinkedList sont dans un bateau
 
Java SE 8 for Java EE developers
Java SE 8 for Java EE developersJava SE 8 for Java EE developers
Java SE 8 for Java EE developers
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
 
Java SE 8 for Java EE developers
Java SE 8 for Java EE developersJava SE 8 for Java EE developers
Java SE 8 for Java EE developers
 

Dernier

ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTiammrhaywood
 
Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17Celine George
 
Keynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-designKeynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-designMIPLM
 
Judging the Relevance and worth of ideas part 2.pptx
Judging the Relevance  and worth of ideas part 2.pptxJudging the Relevance  and worth of ideas part 2.pptx
Judging the Relevance and worth of ideas part 2.pptxSherlyMaeNeri
 
Types of Journalistic Writing Grade 8.pptx
Types of Journalistic Writing Grade 8.pptxTypes of Journalistic Writing Grade 8.pptx
Types of Journalistic Writing Grade 8.pptxEyham Joco
 
AmericanHighSchoolsprezentacijaoskolama.
AmericanHighSchoolsprezentacijaoskolama.AmericanHighSchoolsprezentacijaoskolama.
AmericanHighSchoolsprezentacijaoskolama.arsicmarija21
 
How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17Celine George
 
Alper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentAlper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentInMediaRes1
 
What is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPWhat is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPCeline George
 
Employee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxEmployee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxNirmalaLoungPoorunde1
 
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdfLike-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdfMr Bounab Samir
 
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...Nguyen Thanh Tu Collection
 
Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17Celine George
 
Full Stack Web Development Course for Beginners
Full Stack Web Development Course  for BeginnersFull Stack Web Development Course  for Beginners
Full Stack Web Development Course for BeginnersSabitha Banu
 
Gas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxGas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxDr.Ibrahim Hassaan
 
How to do quick user assign in kanban in Odoo 17 ERP
How to do quick user assign in kanban in Odoo 17 ERPHow to do quick user assign in kanban in Odoo 17 ERP
How to do quick user assign in kanban in Odoo 17 ERPCeline George
 

Dernier (20)

ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
 
Raw materials used in Herbal Cosmetics.pptx
Raw materials used in Herbal Cosmetics.pptxRaw materials used in Herbal Cosmetics.pptx
Raw materials used in Herbal Cosmetics.pptx
 
Model Call Girl in Bikash Puri Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Bikash Puri  Delhi reach out to us at 🔝9953056974🔝Model Call Girl in Bikash Puri  Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Bikash Puri Delhi reach out to us at 🔝9953056974🔝
 
Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17
 
Keynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-designKeynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-design
 
Judging the Relevance and worth of ideas part 2.pptx
Judging the Relevance  and worth of ideas part 2.pptxJudging the Relevance  and worth of ideas part 2.pptx
Judging the Relevance and worth of ideas part 2.pptx
 
Types of Journalistic Writing Grade 8.pptx
Types of Journalistic Writing Grade 8.pptxTypes of Journalistic Writing Grade 8.pptx
Types of Journalistic Writing Grade 8.pptx
 
AmericanHighSchoolsprezentacijaoskolama.
AmericanHighSchoolsprezentacijaoskolama.AmericanHighSchoolsprezentacijaoskolama.
AmericanHighSchoolsprezentacijaoskolama.
 
How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17
 
Alper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentAlper Gobel In Media Res Media Component
Alper Gobel In Media Res Media Component
 
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdfTataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
 
9953330565 Low Rate Call Girls In Rohini Delhi NCR
9953330565 Low Rate Call Girls In Rohini  Delhi NCR9953330565 Low Rate Call Girls In Rohini  Delhi NCR
9953330565 Low Rate Call Girls In Rohini Delhi NCR
 
What is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPWhat is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERP
 
Employee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxEmployee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptx
 
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdfLike-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
 
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
HỌC TỐT TIẾNG ANH 11 THEO CHƯƠNG TRÌNH GLOBAL SUCCESS ĐÁP ÁN CHI TIẾT - CẢ NĂ...
 
Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17Field Attribute Index Feature in Odoo 17
Field Attribute Index Feature in Odoo 17
 
Full Stack Web Development Course for Beginners
Full Stack Web Development Course  for BeginnersFull Stack Web Development Course  for Beginners
Full Stack Web Development Course for Beginners
 
Gas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxGas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptx
 
How to do quick user assign in kanban in Odoo 17 ERP
How to do quick user assign in kanban in Odoo 17 ERPHow to do quick user assign in kanban in Odoo 17 ERP
How to do quick user assign in kanban in Odoo 17 ERP
 

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

  • 1. Java 8 Streams & Collectors Patterns, performance, parallelization @JosePaumard
  • 6.
  • 7.
  • 8.
  • 9.
  • 10. @JosePaumard #J8Stream Code & slides 1st part: slides -Stream -Operations -State -Reduction -Collectors 2nd part: live coding! -Movies & actors -Shakespeare
  • 11. Questions ? #J8Stream @JosePaumard
  • 14. @JosePaumard #J8Stream What is a stream? Answer 1: a typed interface public interface Stream<T> extends BaseStream<T, Stream<T>> { // ... }
  • 15. @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>> { // ... }
  • 16. @JosePaumard #J8Stream What is a stream? What can I do with it?
  • 17. @JosePaumard #J8Stream What is a stream? What can I do with it? Answer: efficiently process high volumes of data, but also small ones
  • 18. @JosePaumard #J8Stream What is a stream? What does efficiently mean?
  • 19. @JosePaumard #J8Stream What is a stream? What does efficiently mean? Two things:
  • 20. @JosePaumard #J8Stream What is a stream? What does efficiently mean? Two things: 1)in parallel, to leverage multicore CPU
  • 21. @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
  • 22. @JosePaumard #J8Stream What is a stream? Why cant a collection be a stream?
  • 23. @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!
  • 24. @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!
  • 25. @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…
  • 26. @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
  • 27. @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
  • 28. @JosePaumard #J8Stream So: what is a Stream? Answers:
  • 29. @JosePaumard #J8Stream So: what is a Stream? Answers: 1)an object on which I can define operations
  • 30. @JosePaumard #J8Stream So: what is a Stream? Answers: 1)an object on which I can define operations 2)that does not hold any data
  • 31. @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
  • 32. @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 »
  • 33. @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
  • 34. @JosePaumard #J8Stream How can I build a Stream? Many patterns!
  • 35. @JosePaumard #J8Stream How can I build a Stream? Many patterns! Let us take one: List<Person> persons = ... ; Stream<Person> stream = persons.stream() ;
  • 36. @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)) ;
  • 37. @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) ;
  • 38. @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
  • 39. @JosePaumard #J8Stream Operation: forEach() First operation: forEach() forEach(): takes a Consumer<T> as a parameter @FunctionalInterface public interface Consumer<T> { void accept(T t) ; }
  • 40. @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) ; }
  • 41. @JosePaumard #J8Stream Functional interface Definition: an interface with only one abstract method
  • 42. @JosePaumard #J8Stream Functional interface Definition: an interface with only one abstract method (methods from Object do not count)
  • 43. @JosePaumard #J8Stream Functional interface Definition: an interface with only one abstract method (methods from Object do not count) (default & static methods do not count)
  • 44. @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
  • 45. @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
  • 46. @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); }; } }
  • 47. @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); }; } }
  • 48. @JosePaumard #J8Stream Default methods New concept in Java 8!
  • 49. @JosePaumard #J8Stream Default methods New concept in Java 8! Added to allow the adding of methods in interfaces without breaking the old implementations
  • 50. @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
  • 51. @JosePaumard #J8Stream Collection.stream() public interface Collection<E> { default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } }
  • 52. @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); } }
  • 53. @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); }; } }
  • 54. @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) ;
  • 55. @JosePaumard #J8Stream Back to the Consumer interface List<String> list = new ArrayList<>() ; Consumer<String> c1 = list::add ; Consumer<String> c2 = System.out::println ;
  • 56. @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
  • 57. @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?
  • 58. @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?
  • 59. @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!
  • 60. @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)) ;
  • 61. @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 !
  • 62. @JosePaumard #J8Stream Back to Stream So far we saw: -forEach(Consumer) -peek(Consumer)
  • 63. @JosePaumard #J8Stream Back to Stream 3rd method: filter(Predicate)
  • 64. @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) ;
  • 65. @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) ;
  • 66. @JosePaumard #J8Stream Interface Predicate Another functional interface @FunctionalInterface public interface Predicate<T> { boolean test(T t) ; }
  • 67. @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() { ... } }
  • 68. @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) ; }
  • 69. @JosePaumard #J8Stream Interface Predicate: patterns Predicate<Integer> p1 = i -> i > 20 ; Predicate<Integer> p2 = i -> i < 30 ; Predicate<Integer> p3 = i -> i == 0 ;
  • 70. @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
  • 71. @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
  • 72. @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) { ... } }
  • 73. @JosePaumard #J8Stream Interface Predicate static <T> Predicate<T> isEqual(Object o) { return t -> o.equals(t) ; }
  • 74. @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) ; }
  • 75. @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 ; }
  • 76. @JosePaumard #J8Stream Interface Predicate We also have: @FunctionalInterface public interface BiPredicate<T, U> { boolean test(T t, U u); }
  • 77. @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) ;
  • 78. @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) ;
  • 79. @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) ;
  • 80. @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) ;
  • 81. @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) ;
  • 82. @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) ;
  • 83. @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) ;
  • 84. @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) ;
  • 85. @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) ;
  • 86. @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
  • 87. @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
  • 88. @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
  • 89. @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…
  • 90. @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 !
  • 91. @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 !
  • 92. @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 !
  • 93. @JosePaumard #J8Stream What do we have so far? We saw: -forEach(Consumer) -peek(Consumer) -filter(Predicate)
  • 94. @JosePaumard #J8Stream What do we have so far? We saw: -forEach(Consumer) -peek(Consumer) -filter(Predicate) The notion of lazyness / intermediate call
  • 95. @JosePaumard #J8Stream Let us carry on And see the mapping operation
  • 96. @JosePaumard #J8Stream Mapping Mapping operation List<Person> list = ... ; Stream<Person> stream = list.stream() ; Stream<String> names = stream.map(person -> person.getName()) ;
  • 97. @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()) ;
  • 98. @JosePaumard #J8Stream Interface Function The map() method takes a Function: @FunctionalInterface public interface Function<T, R> { R apply(T t) ; }
  • 99. @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) ; }
  • 100. @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) ; }
  • 101. @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) ; }
  • 102. @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 ; } }
  • 103. @JosePaumard #J8Stream Other functions There are special types of functions: @FunctionalInterface public interface UnaryOperator<T> extends Function<T, T> { }
  • 104. @JosePaumard #J8Stream Other functions There are special types of functions: @FunctionalInterface public interface BiFunction<T, U, R> { R apply(T t, U u); }
  • 105. @JosePaumard #J8Stream Other functions There are special types of functions: @FunctionalInterface public interface BinaryOperator<T> extends BiFunction<T, T, T> { }
  • 106. @JosePaumard #J8Stream What do we have so far? We saw: -forEach(Consumer) -peek(Consumer) -filter(Predicate) -map(Function)
  • 107. @JosePaumard #J8Stream Let us carry on Method flatMap()
  • 108. @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) ;
  • 109. @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>>
  • 110. @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>>
  • 111. @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();
  • 112. @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>
  • 113. @JosePaumard #J8Stream Method flatMap() flatMap() = flattens a Stream Signature: <R> Stream<R> flatMap(Function<T, Stream<R>> mapper) ;
  • 114. @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) ;
  • 115. @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
  • 116. @JosePaumard #J8Stream What do we have so far? And what about reductions?
  • 117. @JosePaumard #J8Stream Reduction Reduction method: List<Integer> ages = ... ; Stream<Integer> stream = ages.stream() ; Integer sum = stream.reduce(0, (age1, age2) -> age1 + age2) ;
  • 118. @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) ;
  • 119. @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) ;
  • 120. @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) ;
  • 121. @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) ;
  • 122. @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) ;
  • 123. @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
  • 124. @JosePaumard #J8Stream Reduction What is going to happen if the reduction operation has no identity value?
  • 125. @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…
  • 126. @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) ;
  • 127. @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) ;
  • 128. @JosePaumard #J8Stream Reduction Associative, or not associative? red1 = (i1, i2) -> i1 + i2 ;
  • 129. @JosePaumard #J8Stream Reduction Associative, or not associative? red1 = (i1, i2) -> i1 + i2 ;  red2 = (i1, i2) -> i1 > i2 ? i1 : i2 ;
  • 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 ;
  • 131. @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 ;
  • 132. @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 ;
  • 133. @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 ;
  • 134. @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 ; 
  • 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) ;
  • 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, Integer::max) ;
  • 137. @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
  • 138. @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
  • 139. @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
  • 140. @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
  • 141. @JosePaumard #J8Stream Example of max The reduction with a max has a problem : why?
  • 142. @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
  • 143. @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
  • 144. @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()) ;
  • 145. @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 { ... }
  • 146. @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 { ... }
  • 147. @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
  • 148. @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
  • 149. @JosePaumard #J8Stream Optional: more patterns An Optional can be seen as a special Stream with zero or one element void ifPresent(Consumer<T> consumer) ;
  • 150. @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) ;
  • 151. @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) ;
  • 152. @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) ;
  • 153. @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)) ; } }
  • 154. @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]
  • 155. @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]
  • 156. @JosePaumard #J8Stream Optional: new patterns sighted! Function<Double, Optional<Double>> f = d -> NewMath.inv(d) // Optional<Double> .flatMap(d -> NewMath.sqrt(d))// Optional<Double>
  • 157. @JosePaumard #J8Stream Optional: new patterns sighted! Function<Double, Optional<Double>> f = d -> NewMath.inv(d) // Optional<Double> .flatMap(NewMath::sqrt); // Optional<Double>
  • 158. @JosePaumard #J8Stream Optional: new patterns sighted! d -> NewMath.inv(d) // Optional<Double> .flatMap(NewMath::sqrt) // Optional<Double> .map(Stream::of) // Optional<Stream<Double>>
  • 159. @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>
  • 160. @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>
  • 161. @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>
  • 162. @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()) ;
  • 163. @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) ;
  • 164. @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) ;
  • 165. @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!)
  • 166. @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
  • 167. @JosePaumard #J8Stream Terminal operation Example List<Person> persons = ... ; ... = persons.map(person -> person.getAge()) // Stream<Integer> .filter(age -> age > 20) // Stream<Integer> .min(Comparator.naturalOrder()) ;
  • 168. @JosePaumard #J8Stream Terminal operation Example List<Person> persons = ... ; ... = persons.map(Person::getAge) // Stream<Integer> .filter(age -> age > 20) // Stream<Integer> .min(Comparator.naturalOrder()) ;
  • 169. @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
  • 170. @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
  • 171. @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
  • 172. @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
  • 173. @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
  • 174. @JosePaumard #J8Stream What is a Stream? Pipeline approach: 1)we define the operations 2)we trigger the computations by calling a terminal operation
  • 175. @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
  • 176. @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); }
  • 177. @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) ; }
  • 178. @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); }
  • 179. @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); }
  • 180. @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);
  • 181. @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);
  • 182. @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();
  • 183. @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();
  • 184. @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(); }
  • 185. @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; }
  • 186. @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; }
  • 187. @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
  • 188. @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 -
  • 189. @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()) ;
  • 190. @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()) ;
  • 191. @JosePaumard #J8Stream Stream implementation Complex! Two parts: 1)algorithms are in ReferencePipeline 2)data access: Spliterator, can be overriden
  • 192. @JosePaumard #J8Stream A few words on Comparator We wrote: // Comparator interface Comparator cmp = Comparator.naturalOrder() ;
  • 193. @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; }
  • 194. @JosePaumard #J8Stream A few words on Comparator // Comparators class enum NaturalOrderComparator implements Comparator<Comparable<Object>> { INSTANCE; }
  • 195. @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; } }
  • 196. @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(); } }
  • 197. @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) ;
  • 198. @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)); }
  • 199. @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)); }
  • 200. @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)); }
  • 201. @JosePaumard #J8Stream A few words on Comparator Method thenComparing() // Comparator interface default <U> Comparator<T> thenComparing(Function<T, U> keyExtractor) { return thenComparing(comparing(keyExtractor)); }
  • 202. @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)); }
  • 203. @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); }; }
  • 204. @JosePaumard #J8Stream What do we have so far? API Stream -intermediate operations -terminal operations -implementation built on 2 classes
  • 205. @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) ;
  • 206. @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) ;
  • 207. @JosePaumard #J8Stream Stateless / stateful operations This code: ArrayList<Person> persons = ... ; List<String> names = persons.map(Person::getLastName) .collect(Collectors.toList()) ;
  • 208. @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()) ;
  • 209. @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()) ;
  • 210. @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()) ;
  • 211. @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
  • 212. @JosePaumard #J8Stream Stream & performance Two elements: -lazy processing, on one pass over the data -parallel processing
  • 213. @JosePaumard #J8Stream Stream & performance Two elements: -lazy processing, on one pass over the data -parallel processing Stream<T> versus IntStream, LongStream, DoubleStream
  • 214. @JosePaumard #J8Stream Stream & performance Let see this example again: ArrayList<Person> persons = ... ; persons.stream() .map(Person::getAge) .filter(age -> age > 20) .sum() ;
  • 215. @JosePaumard #J8Stream Stream & performance Let see this example again: ArrayList<Person> persons = ... ; persons.stream() // Stream<Person> .map(Person::getAge) .filter(age -> age > 20) .sum() ;
  • 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) .sum() ;
  • 217. @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() ;
  • 218. @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>
  • 219. @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() ;
  • 220. @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() ;
  • 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) .sum() ;
  • 222. @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() ;
  • 223. @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() ;
  • 224. @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() ;
  • 225. @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() ;
  • 226. @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() ;
  • 227. @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() ;
  • 228. @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() ;
  • 229. @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
  • 230. @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) ;
  • 231. @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() ;
  • 232. @JosePaumard #J8Stream Reduction A reduction can be seen as a SQL agregation (sum, min, max, avg, etc…)
  • 233. @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
  • 235. @JosePaumard #J8Stream Reduction Example: sum() The result is an integer, its initial value being 0
  • 236. @JosePaumard #J8Stream Reduction Example: sum() The result is an integer, its initial value being 0 Adding an element to the result is… adding
  • 237. @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 »
  • 238. @JosePaumard #J8Stream Reduction So we have 3 operations:
  • 239. @JosePaumard #J8Stream Reduction So we have 3 operations: -the definition of a container, which holds the result
  • 240. @JosePaumard #J8Stream Reduction So we have 3 operations: -the definition of a container, which holds the result -adding an element to that container
  • 241. @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
  • 242. @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
  • 243. @JosePaumard #J8Stream Reduction So a reduction is based on 3 operations: -a constructor: Supplier -an accumulator: Function -a combiner: Function
  • 244. @JosePaumard #J8Stream Reduction So a reduction is based on 3 operations: -a constructor: Supplier -an accumulator: Function -a combiner: Function () -> new StringBuffer() ;
  • 245. @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) ;
  • 246. @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) ;
  • 247. @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 ;
  • 248. @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 ) ;
  • 249. @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() ) ;
  • 250. @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(", ") ) ;
  • 251. @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(", ", "{", "}") ) ;
  • 252. @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) ;
  • 253. @JosePaumard #J8Stream Reduction Example 2: -a constructor: Supplier -an accumulator: Function -a combiner: Function ArrayList::new ; Collection::add ; Collection::allAll ;
  • 254. @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 ) ;
  • 255. @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() ) ;
  • 256. @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 ) ;
  • 257. @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() ) ;
  • 258. @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) ) ;
  • 259. @JosePaumard #J8Stream Collectors Collectors class: 33 static methods An amazing toolbox!
  • 260. @JosePaumard #J8Stream Collectors: groupingBy HashMap: age / list of the people Map<Integer, List<Person>> result = persons.stream() .collect( Collectors.groupingBy(Person::getAge) ) ;
  • 261. @JosePaumard #J8Stream Collectors: groupingBy HashMap: age / # of people Map<Integer, Long> result = persons.stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.counting() // « downstream collector » ) ) ;
  • 262. @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 ) // ) ) ;
  • 263. @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 ) ) ) ;
  • 264. @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) ) ) ) ;
  • 265. @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) ) ) ) ;
  • 266. @JosePaumard #J8Stream Wrap-up Stream + Collectors = New tools for data processing (map / filter / reduce) 1)lazy execution 2)parallelism Live coding to come!
  • 267. @JosePaumard #J8Stream Wrap-up More to come: -use cases -live coding!
  • 269. Java 8 Streams & Collectors Patterns, performance, parallelization @JosePaumard
  • 270. Questions ? #J8Stream @JosePaumard
  • 271. « movies and actors » https://github.com/JosePaumard/jdk8-lambda-tour http://introcs.cs.princeton.edu/java/data/
  • 272. @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)
  • 273. @JosePaumard #J8Stream Greatest release year 1st question: which year saw the most movies?
  • 274. @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
  • 275. @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
  • 276. @JosePaumard #J8Stream Greatest release year Live coding
  • 277. @JosePaumard #J8Stream Greatest release year 1st question: which year saw the most movies? Solution: map / reduce
  • 278. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor?
  • 279. @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
  • 280. @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()) ;
  • 281. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream() .collect( ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  • 282. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream() .collect( Collectors.toMap( ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  • 283. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream() .collect( Collectors.toMap( actor -> actor, ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  • 284. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? actors.stream() .collect( Collectors.toMap( Function.identity(), ) ) .entrySet().stream() .max(Map.Entry.comparingByValue()).get() ;
  • 285. @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() ;
  • 286. @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() ;
  • 287. @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() ;
  • 288. @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()) ;
  • 289. @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()) ;
  • 290. @JosePaumard #J8Stream Most seen actor Live coding
  • 291. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? Answer: Frank Welker
  • 292. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? Answer: Frank Welker … and in fact he’s not really the most « seen » actor
  • 293. @JosePaumard #J8Stream Most seen actor 2nd question: most seen actor? Answer: Frank Welker
  • 294. @JosePaumard #J8Stream Most seen actor 2nd question: most seen heard actor? Answer: Frank Welker
  • 295. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year?
  • 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
  • 297. @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
  • 298. @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() ;
  • 299. @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() ;
  • 300. @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
  • 301. @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
  • 302. @JosePaumard #J8Stream Most seen actor in a year Live coding
  • 303. @JosePaumard #J8Stream Most seen actor in a year 3rd question: most seen actor in a given year?
  • 304. @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
  • 305. @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
  • 306. « Shakespeare plays Scrabble » https://github.com/JosePaumard/jdk8-lambda-tour http://introcs.cs.princeton.edu/java/data/
  • 307. @JosePaumard #J8Stream Scrabble Two files: -OSPD = official personnal Scrabble dictionary -The words used by Shakespeare
  • 308. @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} ;
  • 309. @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
  • 310. @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
  • 311. @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
  • 312. @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
  • 313. @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
  • 314. @JosePaumard #J8Stream Scrabble: score of a word Live coding
  • 315. @JosePaumard #J8Stream Scrabble: score of a word 1st question: how to compute the score of a word = map / reduce
  • 316. @JosePaumard #J8Stream Scrabble: score of Shakespeare 2nd question: compute the best word of Shakespeare
  • 317. @JosePaumard #J8Stream Scrabble: score of Shakespeare 2nd question: compute the best word of Shakespeare 1)Histogram: score of the words / list of the words
  • 318. @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
  • 319. @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
  • 320. @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
  • 321. @JosePaumard #J8Stream Scrabble: score of Shakespeare Live coding
  • 322. @JosePaumard #J8Stream Scrabble: score of Shakespeare 3rd question: filter out the wrong words We need to add a filtering step
  • 323. @JosePaumard #J8Stream Scrabble: score of Shakespeare Live coding
  • 324. @JosePaumard #J8Stream Scrabble: score of Shakespeare 3rd question: filter out the wrong words Solution: map / filter / reduce
  • 325. @JosePaumard #J8Stream Scrabble: score of Shakespeare Question: can one really write this word?
  • 326. @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} ;
  • 327. @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} ;
  • 328. @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} ;
  • 329. @JosePaumard #J8Stream Filtering V2 4th question: how to check if I have the available letters? 1 1 2 2 1 1 needed letters
  • 330. @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
  • 331. @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
  • 333. @JosePaumard #J8Stream Filtering V2 4th question: how to check if I have the available letters? Solution: map / filter / reduce
  • 334.
  • 335. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: and what about using blanks?
  • 336. @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} ;
  • 337. @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} ;
  • 338. @JosePaumard #J8Stream Scrabble: use of blanks It has 2 impacts: -on the filtering of the words -on the computation of the score
  • 339. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: how to compute the score? 1 1 2 2 1 1
  • 340. @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
  • 341. @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
  • 342. @JosePaumard #J8Stream Scrabble: use of blanks Live coding
  • 343. @JosePaumard #J8Stream Scrabble: use of blanks 5th question: how to compute the score? Solution: map / filter / reduce
  • 344. @JosePaumard #J8Stream Scrabble: use of blanks 6th question: how many blanks do we need? 1 1 2 2 1 1
  • 345. @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
  • 346. @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
  • 347. @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
  • 348. @JosePaumard #J8Stream Scrabble: use of blanks Live coding
  • 349. @JosePaumard #J8Stream Use of a blank 6th question: how many blanks do we need? Solution: map / reduce
  • 350.
  • 351.
  • 352. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score?
  • 353. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score?
  • 354. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: what about the Double letter score?
  • 355. @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
  • 356. @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)!
  • 357. @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
  • 358. @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()
  • 359. @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()
  • 360. @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!
  • 361. @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!
  • 362. @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!
  • 363. @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!
  • 364. @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) ;
  • 365. @JosePaumard #J8Stream Scrabble: and what about the board? Live coding
  • 366. @JosePaumard #J8Stream Scrabble: and what about the board? 7th question: can we take the Double letter score? Solution: map / reduce
  • 368. @JosePaumard #J8Stream Conclusion Streams + Collectors = no need to use the Iterator pattern any more
  • 369. @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
  • 370. @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