SlideShare ist ein Scribd-Unternehmen logo
1 von 301
Downloaden Sie, um offline zu lesen
JDK 8 & Lambdas
Lambdas, Streams & Collectors
@JosePaumard
Why were they introduced ?
@JosePaumard
Why were they introduced ?
How will they change the way we build
applications ?
@JosePaumard
@JosePaumard
Publisher: Addison-Wesley Professional;
1 edition November 10, 1994
@JosePaumard
In stock.
Ships from and sold by Amazon.com. Gift-wrap available.
Publisher: Addison-Wesley Professional;
1 edition November 10, 1994
@JosePaumard
@JosePaumard
@JosePaumard
Let’s introduce the lambdas
Let’s introduce the lambdas
on a simple example
A very simple example
public class Person {
private String name ;
private int age ;
// constructors
// getters / setters
}
List<Person> list = new ArrayList<>() ;
A plain old bean…
… and a good old list
int sum = 0 ;
// I need a default value in case
// the list is empty
int average = 0 ;
for (Person person : list) {
sum += person.getAge() ;
}
if (!list.isEmpty()) {
average = sum / list.size() ;
}
Average of the ages
int sum = 0 ;
int n = 0 ;
int average = 0 ;
for (Person person : list) {
if (person.getAge() > 20) {
n++ ;
sum += person.getAge() ;
}
}
if (n > 0) {
average = sum / n ;
}
Trickier : average of the ages of people older than 20
Trickier : average of the ages of people older than 20
« imperative programming »
int sum = 0 ;
int n = 0 ;
int average = 0 ;
for (Person person : list) {
if (person.getAge() > 20) {
n++ ;
sum += person.getAge() ;
}
}
if (n > 0) {
average = sum / n ;
}
select avg(age)
from Person
where age > 20
… it does not have to be like that !
This is a description of the result
select avg(age)
from Person
where age > 20
… it does not have to be like that !
This is a description of the result
In that case, the DB server is free to compute the
result the way it sees fit
© SQL language, 1974
Person age age > 20 sum
1st step : mapping
map
Person age age > 20 sum
1st step : mapping
Mapping :
- takes a list of a given type
- gives another list of a different type
- same number of elements
map
Person age age > 20 sum
2nd step : filtering
filtermap
Person age age > 20 sum
2nd step : filtering
Filtering :
- takes a list of a given type
- gives another list of a the same type
- less elements
filtermap
Person age age > 20 sum
3rd step : reduction
reducefiltermap
Person age age > 20 sum
3rd step : reduction
Reduction : agregation of all the elements
in a single one
Ex : average, sum, min, max, etc…
reducefiltermap
How can I model that ?
The JDK 7 way
Create an interface to model the mapper…
public interface Mapper<T, V> {
public V map(T t) ;
}
public class PersonToAgeMapper implements Mapper<Person, Integer> {
public Integer map(Person p) {
return p.getAge() ;
}
}
The JDK 7 way
… and create an implementation …
public interface Mapper<T, V> {
public V map(T t) ;
}
Mapper<Person, Integer> mapper = new Mapper<Person, Integer>() {
public Integer map(Person p) {
return p.getAge() ;
}
}
The JDK 7 way
… that could be anonymous
public interface Mapper<T, V> {
public V map(T t) ;
}
The JDK 7 way
We can do the same for the filtering
public interface Predicate<T> {
public boolean filter(T t) ;
}
public class AgePredicate implements Predicate<Integer> {
public boolean filter(Integer i) {
return i > 20 ;
}
}
The JDK 7 way
We can do the same for the filtering
public interface Predicate<T> {
public boolean filter(T t) ;
}
AgePredicate predicate = new Predicate<Integer>() {
public boolean filter(Integer i) {
return i > 20 ;
}
}
The JDK 7 way
We can do the same for the filtering
public interface Predicate<T> {
public boolean filter(T t) ;
}
The JDK 7 way
And for the reduction
public interface Reducer<T> {
public T reduce(T t1, T t2) ;
}
public class Sum implements Reducer<Integer> {
public Integer reduce(Integer i1, Integer i2) {
return i1 + i2 ;
}
}
The JDK 7 way
And for the reduction
public interface Reducer<T> {
public T reduce(T t1, T t2) ;
}
Reducer<Integer> reduction = new Reducer<Integer>() {
public Integer reduce(Integer i1, Integer i2) {
return i1 + i2 ;
}
}
The JDK 7 way
And for the reduction
public interface Reducer<T> {
public T reduce(T t1, T t2) ;
}
The JDK 7 way
So the whole map / filter / reduce looks like this
1) Create 3 interfaces public interface Mapper<T, V> {
public V map(T t) ;
}
public interface Predicate<T> {
public boolean filter(T t) ;
}
public interface Reducer<T> {
public T reduce(T t1, T t2) ;
}
The JDK 7 way
So the whole map / filter / reduce looks like this
1) Create 3 interfaces
2) Apply the pattern
List<Person> persons = ... ;
int sum =
persons.map(
new Mapper<Person, Integer>() {
public Integer map(Person p) {
return p.getAge() ;
}
})
.filter(
new Filter<Integer>() {
public boolean filter(Integer age) {
return age > 20 ;
}
})
.reduce(0,
new Reducer<Integer>() {
public Integer recude(Integer i1, Integer i2) {
return i1 + i2 ;
}
}
}) ;
The JDK 7 way
So the whole map / filter / reduce looks like this
1) Create 3 interfaces
2) Apply the pattern
List<Person> persons = ... ;
int sum =
persons.map(
new Mapper<Person, Integer>() {
public Integer map(Person p) {
return p.getAge() ;
}
})
.filter(
new Filter<Integer>() {
public boolean filter(Integer age) {
return age > 20 ;
}
})
.reduce(0,
new Reducer<Integer>() {
public Integer recude(Integer i1, Integer i2) {
return i1 + i2 ;
}
}
}) ;
The JDK 8 way
mapper = new Mapper<Person, Integer>() {
public Integer map(Person person) {
return person.getAge() ;
}
}
The JDK 8 way
Let’s rewrite our mapper
mapper = new Mapper<Person, Integer>() {
public Integer map(Person person) { // 1 method
return person.getAge() ;
}
}
The JDK 8 way
Let’s rewrite our mapper
mapper = new Mapper<Person, Integer>() {
public Integer map(Person person) { // 1 method
return p.getAge() ;
}
}
The JDK 8 way
mapper = (Person person) ;
we take a
person p
Let’s rewrite our mapper
mapper = new Mapper<Person, Integer>() {
public Integer map(Person person) { // 1 method
return person.getAge() ;
}
}
The JDK 8 way
mapper = (Person person) -> ;
and then …
Let’s rewrite our mapper
mapper = new Mapper<Person, Integer>() {
public Integer map(Person person) { // 1 method
return person.getAge() ;
}
}
The JDK 8 way
mapper = (Person person) -> person.getAge() ;
… return the age of p
Let’s rewrite our mapper
Let’s rewrite our mapper
mapper = new Mapper<Person, Integer>() {
public Integer map(Person person) { // 1 method
return person.getAge() ;
}
}
The JDK 8 way
mapper = (Person person) -> person.getAge() ;
Let’s rewrite our mapper
The compiler can recognize this as an implementation of
Mapper
mapper = new Mapper<Person, Integer>() {
public Integer map(Person person) { // 1 method
return person.getAge() ;
}
}
The JDK 8 way
mapper = (Person person) -> person.getAge() ;
What if …
… there is more than one statement ?
The return has to be explicit
mapper = Person person -> {
System.out.println("Mapping " + person) ;
return person.getAge() ;
}
What if …
…I have no return value ?
consumer = Person person -> p.setAge(p.getAge() + 1) ;
What if …
…I have more than one argument ?
Or :
reducer = (int i1, int i2) -> {
return i1 + i2 ;
}
reducer = (int i1, int i2) -> i1 + i2 ;
The JDK 8 way
How can the compiler recognize the implementation of
map() ?
mapper = (Person person) -> person.getAge() ;
The JDK 8 way
How can the compiler recognize the implementation of
map() ?
1) There’s only one method in Mapper
mapper = (Person person) -> person.getAge() ;
The JDK 8 way
How can the compiler recognize the implementation of
map() ?
1) There’s only one method in Mapper
2) Both the parameters and the return types are
compatible
mapper = (Person person) -> person.getAge() ;
The JDK 8 way
How can the compiler recognize the implementation of
map() ?
1) There’s only one method in Mapper
2) Both the parameters and the return types are
compatible
3) Thrown exceptions (if any) are compatible
mapper = (Person person) -> person.getAge() ;
More lambdas
Writing more lambdas becomes natural :
mapper = (Person person) -> person.getAge() ; // mapper
filter = (int age) -> age > 20 ; // filter
reducer = (int i1, int i2) -> i1 + i2 ; // reducer
More lambdas
And most of the time, the compiler understands this :
The « parameter types » can be omitted
mapper = person -> person.getAge() ; // mapper
filter = age -> age > 20 ; // filter
reducer = (i1, i2) -> i1 + i2 ; // reducer
Just a remark on the reduction
How does it really work ?
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
Reduction
2 examples :
Caveat :
the result is always reproductible in serial
it’s not in parallel
Reducer r1 = (i1, i2) -> i1 + i2 ; // Ok
Reducer r2 = (i1, i2) -> i1*i1 + i2*i2 ; // Oooops
So far
A lambda expression is an alternative
to write instances of anonymous inner classes
Other syntaxes
Very often one writes
This syntax is also possible :
mapper = person -> person.getAge() ;
mapper = Person::getAge ; // non static method
Other syntaxes
Other example :
Or :
sum = (i1, i2) -> i1 + i2 ;
sum = Integer::sum ; // static method, new !
max = (i1, i2) -> i1 > i2 ? i1 : i2 ;
max = Integer::max ; // static method, new !
Other syntaxes
Other example :
toLower = String::toLowerCase ;
// !!!! NO NO NO !!!!
toLowerFR = String::toLowerCase(Locale.FRANCE) ;
More on the lambdas
Questions :
What model for a lambda ?
Questions :
What model for a lambda ?
Can I put a lambda in a variable ?
Questions :
What model for a lambda ?
Can I put a lambda in a variable ?
Is a lambda an object ?
Modelization
A lambda is an instance of a « functional interface »
@FunctionalInterface
public interface Consumer<T> {
public void accept(T t) ;
}
Modelization
A lambda is an instance of a « functional interface »
- only one abstract method (methods from Object dont
count)
- can be annotated by @FunctionalInterface (optional)
@FunctionalInterface
public interface Consumer<T> {
public void accept(T t) ;
}
Putting a lambda in a variable
Example of a consumer
So :
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s) ;
}
} ;
Consumer<String> c = s -> System.out.println(s) ;
Putting a lambda in a variable
Example of a consumer
So :
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s) ;
}
} ;
Consumer<String> c = s -> System.out.println(s) ;
Question : what is s ?
Putting a lambda in a variable
Example of a consumer
So :
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s) ;
}
} ;
Consumer<String> c = s -> System.out.println(s) ;
Answer : the compiler
infers that it is a String
Putting a lambda in a variable
Example of a consumer
So :
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s) ;
}
} ;
Consumer<String> c = System.out::println ;
Questions :
What model for a lambda ?
answer : with a functional interface
Can I put a lambda in a variable ?
answer : yes
Is a lambda an object ?
Is a lambda an objet ?
Let’s play the game of 7 errors (with only 1 error)
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s) ;
}
} ;
Consumer<String> c = s -> System.out.println(s) ;
Is a lambda an objet ?
Let’s play the game of 7 errors (with only 1 error)
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s) ;
}
} ;
Consumer<String> c = s -> System.out.println(s) ;
Questions :
What model for a lambda ?
answer : with a functional interface
Can I put a lambda in a variable ?
answer : yes
Is a lambda an object ?
answer : no
Plenty of lambdas :
java.util.function
Java.util.function
This new package holds the functional interfaces
There are 43 of them
Java.util.function
Supplier : alone in its kind
Consumer / BiConsumer
Function / BiFunction (UnaryOperator / BinaryOperator)
Predicate / BiPredicate
Plus the primitive types versions
Supplier
A supplier supplies an object
public interface Supplier<T> {
T get() ;
}
Consumer
A consumer just … accepts an object
public interface Consumer<T> {
void accept(T t) ;
}
Consumer<String> c1 = s -> System.out.println(s) ;
Consumer<String> c2 = ... ;
Consumer<String> c3 = c1.andThen(c2) ;
persons.stream().forEach(c3) ;
Function
A function takes an object and returns another one
Can be chained and / or composed
public interface Function<T, R> {
R apply(T t) ;
}
Predicate
A Predicate takes an object and returns a boolean
Can be negated, composed with and / or
public interface Predicate<T> {
boolean test(T t) ;
}
Back to the
map / filter / reduce
pattern
The JDK 7 way
How to apply map / filter / reduce
to List<Person> ?
The JDK 7 way
How to apply map / filter / reduce
to List<Person> ?
The legal way is to iterate over the elements
and apply the pattern
The JDK 7 way
How to apply map / filter / reduce
to List<Person> ?
The legal way is to iterate over the elements
and apply the pattern
One can create a helper method
Applying map to a List
With a helper method, JDK 7
List<Person> persons = new ArrayList<>() ;
List<Integer> ages = // ages is a new list
Lists.map(
persons,
new Mapper<Person, Integer>() {
public Integer map(Person p) {
return p.getAge() ;
}
}
) ;
Applying map to a List
With a helper method, JDK 8 & lambdas
List<Person> persons = new ArrayList<>() ;
List<Integer> ages =
Lists.map(
persons,
person -> person.getAge()
) ;
Applying map to a List
With a helper method, JDK 8 & lambdas
List<Person> persons = new ArrayList<>() ;
List<Integer> ages =
Lists.map(
persons,
Person::getAge
) ;
Putting things together
The map / filter / reduce pattern would look like this
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = Lists.map( persons, p -> p.getAge()) ;
List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ;
int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
Putting things together
The map / filter / reduce pattern would look like this
The idea is to push lambdas to the API, and let it apply
them on its content
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = Lists.map( persons, p -> p.getAge()) ;
List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ;
int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
Putting things together
The map / filter / reduce pattern would look like this
Pro : the API can be optimized
without touching the code : great !
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = Lists.map( persons, p -> p.getAge()) ;
List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ;
int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
Putting things together
The map / filter / reduce pattern would look like this
Pro : the API can be optimized
without touching the code
Cons …
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = Lists.map( persons, p -> p.getAge()) ;
List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ;
int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
Putting things together
1) Suppose persons is a really BIG list
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = Lists.map( persons, p -> p.getAge()) ;
List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ;
int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
Putting things together
1) Suppose persons is a really BIG list
2 duplications : ages & agesGT20
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = Lists.map( persons, p -> p.getAge()) ;
List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ;
int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
Putting things together
1) Suppose persons is a really BIG list
2 duplications : ages & agesGT20
What do we do with them ? Send them to the GC
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = Lists.map( persons, p -> p.getAge()) ;
List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ;
int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
Putting things together
2) Suppose we have a allMatch() reducer
allMatch is true if all the names are shorter than 20 chars
let’s see a possible implementation of allMatch()
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<String> names =
Lists.map(persons, p -> p.getName()) ;
boolean allMatch =
Lists.allMatch(names, n -> n.length() < 20) ;
How could one write allMatch ?
Here is a basic implementation of allMatch
public static <T> boolean allMatch(
List<? extends T> list, Filter<T> filter) {
for (T t : list) {
if (!filter.filter(t)) {
return false ;
}
}
return true ;
}
How could one write allMatch ?
Here is a basic implementation of allMatch
public static <T> boolean allMatch(
List<? extends T> list, Filter<T> filter) {
for (T t : list) {
if (!filter.filter(t)) {
return false ;
}
}
return true ;
}
No need to iterate
over the whole list
Putting things together
When we apply the allMatch() reducer…
… the list names has already been evaluated !
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<String> names =
Lists.map(persons, p -> p.getName()) ;
boolean allMatch =
Lists.allMatch(names, n.length() < 20) ;
Putting things together
When we apply the allMatch() reducer…
… we should have wait to apply the filter
A good way to do that : apply the filter step lazily !
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<String> names =
Lists.map(persons, p -> p.getName()) ;
boolean allMatch =
Lists.allMatch(names, n.length() < 20) ;
Conclusion
Pro : 1
Cons : 2 (at least)
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = Lists.map( persons, p -> p.getAge()) ;
List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ;
int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = Lists.map( persons, p -> p.getAge()) ;
List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ;
int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
Conclusion
Pro : 1
Cons : 2 (at least)
Conclusion
And the same goes for this one
// applying the map / filter / reduce pattern
List<Person> persons = ... ;
List<Integer> ages = persons.map(p -> p.getAge()) ;
List<Integer> agesGT20 = ages.filter(a -> a > 20) ;
int sum = agesGT20.reduce(ages, (i1, i2) -> i1 + i2) ;
Conclusion (again)
We need a new concept to handle BIG lists efficiently
Conclusion (again)
We need a new concept to handle BIG lists efficiently
The Collection framework is not the right one…
Conclusion (again)
We need a new concept to handle BIG lists efficiently
The Collection framework is not the right one
We need something else !
So what pattern
to choose ?
Introduction
Putting map / filter / reduce methods on Collection
would have led to :
And even if it doesnt lead to viable patterns,
it is still a pleasant way of writing things
// map / filter / reduce pattern on collections
int sum = persons
.map(p -> p.getAge())
.filter(a -> a > 20)
.reduce(0, (a1, a2) -> a1 + a2) ;
Introduction
Let’s keep the same kind of pattern and add a stream()
// map / filter / reduce pattern on collections
int sum = persons.stream()
.map(p -> p.getAge())
.filter(a -> a > 20)
.reduce(0, (a1, a2) -> a1 + a2) ;
Introduction
Collection.stream() returns a Stream : new interface
New interface = our hands are free !
// map / filter / reduce pattern on collections
int sum = persons.stream()
.map(p -> p.getAge())
.filter(a -> a > 20)
.reduce(0, (a1, a2) -> a1 + a2) ;
New Collection interface
So we need a new method on Collection
public interface Collection<E> {
// our good old methods
Stream<E> stream() ;
}
New Collection interface
Problem : ArrayList doesnt compile anymore…
Something has to be done !
public interface Collection<E> {
// our good old methods
Stream<E> stream() ;
}
Interfaces
Problem : ArrayList doesnt compile anymore…
Something has to be done !
Something that does not need to change or recompile all
the existing implementations of Collection
New interfaces
Java 8 interfaces
Problem : how to add methods to an interface, without
changing any of the implementations ?
Java 8 interfaces
Problem : how to add methods to an interface, without
changing any of the implementations ?
Solution : change the way interfaces work in Java
Java 8 interfaces
ArrayList needs to know the implementation of stream()…
public interface Collection<E> {
// our good old methods
Stream<E> stream() ;
}
Java 8 interfaces
Let’s put it in the interface !
public interface Collection<E> {
// our good old methods
default Stream<E> stream() {
return ... ;
}
}
Java 8 interfaces
Let’s introduce default methods in Java
Default methods are about interface evolution
Allows the extension of old interfaces
public interface Collection<E> {
// our good old methods
default Stream<E> stream() {
return ... ;
}
}
Default methods
Does it bring multiple inheritance to Java ?
Default methods
Does it bring multiple inheritance to Java ?
Yes ! But we already have it
Default methods
Does it bring multiple inheritance to Java ?
Yes ! But we already have it
public class String
implements Serializable, Comparable<String>, CharSequence {
// ...
}
Default methods
What we have so far is multiple inheritance of type
Default methods
What we have so far is multiple inheritance of type
What we get in Java 8 is multiple inheritance of behavior
Default methods
What we have so far is multiple inheritance of type
What we get in Java 8 is multiple inheritance of behavior
What we dont have is multiple inheritance of state
Default methods
What we have so far is multiple inheritance of type
What we get in Java 8 is multiple inheritance of behavior
What we dont have is multiple inheritance of state
… and this is where the trouble is !
Default methods
Will we have conflicts ?
Default methods
Will we have conflicts ?
Oooh yes…
Default methods
Will we have conflicts ?
Oooh yes…
So we need rules to handle them
Default methods
public class C
implements A, B {
// ...
}
Default methods
public interface A {
default String a() { ... }
}
public interface B {
default String a() { ... }
}
Example #1
public class C
implements A, B {
// ...
}
Example #1
Compile error :
class C inherits unrelated defaults for a() from types A and B
Default methods
public interface A {
default String a() { ... }
}
public interface B {
default String a() { ... }
}
public class C
implements A, B {
// ...
}
Example #2
Class wins !
Default methods
public interface A {
default String a() { ... }
}
public interface B {
default String a() { ... }
}
public class C
implements A, B {
public String a() { ... }
}
Example #2a
I can explicitly call a default implementation
Default methods
public interface A {
default String a() { ... }
}
public interface B {
default String a() { ... }
}
public class C
implements A, B {
public String a() { return B.super.a() ; }
}
Example #3
More specific interfaces wins over less specific
Default methods
public interface A extends B {
default String a() { ... }
}
public interface B {
default String a() { ... }
}
public class C
implements A, B {
// ...
}
2 simple rules
To handle the conflict of multiple inheritance of behavior
2 simple rules
To handle the conflict of multiple inheritance of behavior
1) Class wins !
2 simple rules
To handle the conflict of multiple inheritance of behavior
1) Class wins !
2) More specific interfaces wins over less specific
An example
Everybody who writes an implementation of Iterator
writes this :
public class MyIterator implements Iterator<E> {
// some critical business code
public void remove() {
throw new UnsupportedOperationException("You shouldnt do that") ;
} ;
}
An example
Thanks to Java 8 :
No silly implementation of remove() anymore !
public interface Iterator<E> {
default void remove() {
throw new UnsupportedOperationException("remove") ;
} ;
}
Java 8 interfaces
So the concept of « interface » changed in Java 8
public class HelloWorld {
// souvenir souvenir
public static void main(String[] args) {
System.out.println("Hello world!") ;
} ;
}
Java 8 interfaces
So the concept of « interface » changed in Java 8
I mean, really
public interface HelloWorld {
// souvenir souvenir
public static void main(String[] args) {
System.out.println("Hello world!") ;
} ;
}
Java 8 interfaces
1) Default methods, multiple behavior inheritance
Rules to handle conflicts, solved at compile time
2) Static methods in interfaces
Will bring new patterns and new ways to write APIs
Where are we ?
1) We have a new syntax
2) We have a new pattern to implement
3) We have new interfaces to keep the backward
compatibily
The Stream API
What is a Stream
From a technical point of view : a typed interface
« a stream of String »
What is a Stream
From a technical point of view : a typed interface
Other classes for primitive types :
« a stream of String »
IntStream, LongStream, DoubleStream
It’s a new notion
1) A stream doesnt hold any data
It’s just an object on which one can declare operations
Streams are about « specifying computations »
It’s a new notion
1) A stream doesnt hold any data
2) A stream cant modify its source
Consequence : it can use parallel processing
It’s a new notion
1) A stream doesnt hold any data
2) A stream cant modify its source
3) A source can be infinite
So we need a way to guarantee that computations
will be conducted in finite time
It’s a new notion
1) A stream doesnt hold any data
2) A stream cant modify its source
3) A source can be infinite
4) A stream works lazily
Then optimizations can be made among the different
operations
We need a way / convention to trigger the computations
How can we build a stream ?
Many ways…
1) From a collection : method Collection.stream
Collection<String> collection = ... ;
Stream<String> stream = collection.stream() ;
How can we build a stream ?
Many ways…
1) From a collection : method Collection.stream
2) From an array : Arrays.stream(Object [])
Stream<String> stream2 =
Arrays.stream(new String [] {"one", "two", "three"}) ;
How can we build a stream ?
Many ways…
1) From a collection : method Collection.stream
2) From an array : Arrays.stream(Object [])
3) From factory methods in Stream, IntStream, …
Stream<String> stream1 = Stream.of("one", "two", "three") ;
How can we build a stream ?
Some more patterns
Stream.empty() ; // returns an empty Stream
Stream.of(T t) ; // a stream with a single element
Stream.generate(Supplier<T> s) ;
Stream.iterate(T seed, UnaryOperator<T> f) ;
How can we build a stream ?
Other ways scattered in the JDK
string.chars() ; // returns a IntStream
lineNumberReader.lines() ; // returns a Stream<String>
random.ints() ; // return a IntStream
3 points about Stream
1) Two types of operations
One can declare operations on a Stream
Two types of operations :
1) Intermediate operations : declarations, processed lazily
ex : map, filter
1) Two types of operations
One can declare operations on a Stream
Two types of operations :
1) Intermediate operations : declarations, processed lazily
ex : map, filter
2) Terminal operations : trigger the computations
ex : reduce
A 1st example
Back to our map / filter / reduce example
// map / filter / reduce pattern on collections
int sum = persons.stream()
.map(p -> p.getAge())
.filter(a -> a > 20)
.reduce(0, (a1, a2) -> a1 + a2) ;
Build a stream
on a List
A 1st example
Back to our map / filter / reduce example
// map / filter / reduce pattern on collections
int sum = persons.stream()
.map(p -> p.getAge())
.filter(a -> a > 20)
.reduce(0, (a1, a2) -> a1 + a2) ;
Declare
operations
A 1st example
Back to our map / filter / reduce example
// map / filter / reduce pattern on collections
int sum = persons.stream()
.map(p -> p.getAge())
.filter(a -> a > 20)
.reduce(0, (a1, a2) -> a1 + a2) ;
Triggers the
computation
2) State of a stream
The implementation of Stream has a state :
- SIZED : the number of elements is known
- ORDERED : the order matters (List)
- DISTINCT : all elements are unique (Set)
- SORTED : all elements have been sorted (SortedSet)
2) State of a stream
Some operations change that :
- filtering removes the SIZED
- mapping removes DISTINCT and SORTED
2) State of a stream
And it allows nice optimizations !
- a HashSet cant have doubles so…
2) State of a stream
And it allows nice optimizations !
- a HashSet cant have doubles so…
- distinct() is NOPed on a stream built on a HashSet
2) State of a stream
And it allows nice optimizations !
- a HashSet cant have doubles so…
- distinct() is NOPed on a stream built on a HashSet
- A TreeSet is sorted so…
2) State of a stream
And it allows nice optimizations !
- a HashSet cant have doubles so…
- distinct() is NOPed on a stream built on a HashSet
- A TreeSet is sorted so…
- sorted() is NOPed on a stream built on a TreeSet
3) Stateless / stateful operations
Stateless / stateful operations
Some operations are stateless :
It means that they dont need more information than the
one held by their parameters
persons.stream().map(p -> p.getAge()) ;
3) Stateless / stateful operations
Stateless / stateful operations
Some operations are stateless :
Some need to retain information :
persons.stream().map(p -> p.getAge()) ;
stream.limit(10_000_000) ; // select the 10M first elements
Example
Let’s sort an array of String
Random rand = new Random() ;
String [] strings = new String[10_000_000] ;
for (int i = 0 ; i < strings.length ; i++) {
strings[i] = Long.toHexString(rand.nextLong()) ;
}
Example
Let’s sort an array of String
Soooo Java 7…
Random rand = new Random() ;
String [] strings = new String[10_000_000] ;
for (int i = 0 ; i < strings.length ; i++) {
strings[i] = Long.toHexString(rand.nextLong()) ;
}
Example
Let’s sort an array of String
Better ?
Random rand = new Random() ;
Stream<String> stream =
Stream.generate(
() ->
Long.toHexString(rand.nextLong())
) ;
Example
Let’s sort an array of String
Better !
// Random rand = new Random() ;
Stream<String> stream =
Stream.generate(
() ->
Long.toHexString(ThreadLocalRandom.current().nextLong())
) ;
Example
Let’s sort an array of String
// other way
Stream<String> stream =
ThreadLocalRandom
.current()
.longs() // returns a LongStream
.mapToObj(l -> Long.toHexString(l)) ;
Example
Let’s sort an array of String
// other way
Stream<String> stream =
ThreadLocalRandom
.current()
.longs()
.mapToObj(Long::toHexString) ;
Example
Let’s sort an array of String
// other way
Stream<String> stream =
ThreadLocalRandom
.current()
.longs()
.mapToObj(Long::toHexString)
.limit(10_000_000)
.sorted() ;
T = 4 ms
Example
Let’s sort an array of String
// other way
Stream<String> stream =
ThreadLocalRandom
.current()
.longs()
.mapToObj(Long::toHexString)
.limit(10_000_000)
.sorted() ;
Object [] sorted = stream.toArray() ;
Example
Let’s sort an array of String
// other way
Stream<String> stream =
ThreadLocalRandom
.current()
.longs()
.mapToObj(Long::toHexString)
.limit(10_000_000)
.sorted() ;
Object [] sorted = stream.toArray() ;
T = 14 s
Example
Let’s sort an array of String
// other way
Stream<String> stream =
ThreadLocalRandom
.current()
.longs()
.mapToObj(Long::toHexString)
.limit(10_000_000)
.sorted() ;
Object [] sorted = stream.toArray() ;
T = 14 s
Intermediate calls !
Last word about stream operations
1) There are intermediate and terminal operations
2) A stream is processed on a terminal operation call
Last word about stream operations
1) There are intermediate and terminal operations
2) A stream is processed on a terminal operation call
3) Only one terminal operation is allowed
4) It cannot be processed again
If needed another stream should be built on the source
Parallel Streams
Optimization
The first optimization (well, laziness was first !) we need is
parallelism
The fork / join enable parallel programming since JDK 7
But writing tasks is hard and does not always lead to better
performances
Optimization
The first optimization (well, laziness was first !) we need is
parallelism
The fork / join enable parallel programming since JDK 7
But writing tasks is hard and does not always lead to better
performances
Using the parallel stream API is much more secure
How to build a parallel stream ?
Two patterns
1) Call parallelStream() instead of stream()
2) Call parallel() on an existing stream
Stream<String> s = strings.parallelStream() ;
Stream<String> s = strings.stream().parallel() ;
Is parallelism really that simple ?
Well… yes !
Is parallelism really that simple ?
Well… yes !
… and no
Is parallelism really that simple ?
Example 1 :
« returns the 10M first elements of the source »
persons.stream().limit(10_000_000) ;
Is parallelism really that simple ?
Example 1 :
« returns the 10M first elements of the source »
persons.parallelStream().limit(10_000_000) ;
Is parallelism really that simple ?
Example 1 : performances
Code 1
List<Long> list = new ArrayList<>(10_000_100) ;
for (int i = 0 ; i < 10_000_000 ; i++) {
list1.add(ThreadLocalRandom.current().nextLong()) ;
}
Is parallelism really that simple ?
Example 1 : performances
Code 2
Stream<Long> stream =
Stream.generate(() -> ThreadLocalRandom.current().nextLong()) ;
List<Long> list1 =
stream.limit(10_000_000).collect(Collectors.toList()) ;
Is parallelism really that simple ?
Example 1 : performances
Code 3
Stream<Long> stream =
ThreadLocalRandom.current().longs(10_000_000).mapToObj(Long::new) ;
List<Long> list = stream.collect(Collectors.toList()) ;
Is parallelism really that simple ?
Example 1 : performances
Serial Parallel
Code 1 (for) 270 ms
Code 2 (limit) 310 ms
Code 3 (longs) 250 ms
Is parallelism really that simple ?
Example 1 : performances
Serial Parallel
Code 1 (for) 270 ms
Code 2 (limit) 310 ms 500 ms
Code 3 (longs) 250 ms 320 ms
Is parallelism really that simple ?
Example 2 :
« returns a stream with all the elements of the first stream
followed by all the elements of the second stream »
Stream s3 = Stream.concat(stream1, stream2) ;
Parallelism
Parallelism implies overhead most of the time
Badly configured parallel operations can lead to unneeded
computations that will slow down the overall process
Unnecessary ordering of a stream will lead to performance
hits
Reductions
A simple reduction
Sum of ages
// map / filter / reduce pattern on collections
int sum = persons.stream()
.map(p -> p.getAge())
.filter(a -> a > 20)
.reduce(0, (a1, a2) -> a1 + a2) ;
A simple reduction
It would be nice to be able to write :
But there’s no sum() on Stream<T>
What would be the sense of « adding persons » ?
// map / filter / reduce pattern on collections
int sum = persons.stream()
.map(p -> p.getAge())
.filter(a -> a > 20)
.sum() ;
A simple reduction
It would be nice to be able to write :
But there’s no sum() on Stream<T>
There’s one on IntStream !
// map / filter / reduce pattern on collections
int sum = persons.stream()
.map(p -> p.getAge())
.filter(a -> a > 20)
.sum() ;
A simple reduction
2nd version :
Value if persons is an empty list : 0
// map / filter / reduce pattern on collections
int sum = persons.stream()
.map(Person::getAge)
.filter(a -> a > 20)
.mapToInt(Integer::intValue)
.sum() ;
A simple reduction
2nd version (even better) :
Value if persons is an empty list : 0
// map / filter / reduce pattern on collections
int sum = persons.stream()
.mapToInt(Person::getAge)
.filter(a -> a > 20)
// .mapToInt(Integer::intValue)
.sum() ;
A simple reduction
What about max() and min() ?
How can one chose a default value ?
// map / filter / reduce pattern on collections
....... = persons.stream()
.mapToInt(Person::getAge)
.filter(a -> a > 20)
.max() ;
Problem with the default value
The « default value » is a tricky notion
Problem with the default value
The « default value » is a tricky notion
1) The « default value » is the reduction of the empty set
Problem with the default value
The « default value » is a tricky notion
1) The « default value » is the reduction of the empty set
2) But it’s also the identity element for the reduction
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
@JosePaumard
Problem with the default value
The « default value » is a tricky notion
1) The « default value » is the reduction of the empty set
2) But it’s also the identity element for the reduction
Problem with the default value
Problem : max() and min() have no identity element
eg : an element e for which max(e, a) = a
Problem with the default value
Problem : max() and min() have no identity element
eg : an element e for which max(e, a) = a
0 cant be, max(0, -1) is not -1…
−∞ is not an integer
Problem with the default value
So what is the identity element of max() and min() ?
Problem with the default value
So what is the identity element of max() and min() ?
Answer : there is no identity element for max() or min()
Problem with the default value
So what is the default value of max() and min() ?
Problem with the default value
So what is the default value of max() and min() ?
Answer : there is no default value for max() and min()
Problem with the default value
So what is the returned value of the max() reduction ?
// map / filter / reduce pattern on collections
....... = persons.stream()
.mapToInt(Person::getAge)
.filter(a -> a > 20)
.max() ;
Problem with the default value
So what is the returned value of the max() reduction ?
If it’s int, then the default value will be 0…
// map / filter / reduce pattern on collections
....... = persons.stream()
.mapToInt(Person::getAge)
.filter(a -> a > 20)
.max() ;
Problem with the default value
So what is the returned value of the max() reduction ?
If it’s int, then the default value will be 0…
It it’s Integer, then the default value will be null…
// map / filter / reduce pattern on collections
....... = persons.stream()
.mapToInt(Person::getAge)
.filter(a -> a > 20)
.max() ;
Optionals
Since there’s none, we need another notion
// map / filter / reduce pattern on collections
OptionalInt optionalMax = persons.stream()
.mapToInt(Person::getAge)
.filter(a -> a > 20)
.max() ;
« there might be no
result »
Optionals
What can I do with OptionalInt ?
1st pattern : test if it holds a value
OptionalInt optionalMax = ... ;
int max ;
if (optionalMax.isPresent()) {
max = optionalMax.get() ;
} else {
max = ... ; // decide a « default value »
}
Optionals
What can I do with OptionalInt ?
1st pattern bis : read the held value, giving a default value
OptionalInt optionalMax = ... ;
// get 0 if no held value
int max = optionalMax.orElse(0) ;
Optionals
What can I do with OptionalInt ?
2nd pattern : read the held value, can get an exception
OptionalInt optionalMax = ... ;
// throws NoSuchElementException if no held value
int max = optionalMax.getAsInt() ;
Optionals
What can I do with OptionalInt ?
2nd pattern bis : read the held value, or throw an exception
OptionalInt optionalMax = ... ;
// exceptionSupplier will supply an exception, if no held value
int max = optionalMax.orElseThrow(exceptionSupplier) ;
Available optionals
Optional<T>
OptionalInt, OptionalLong, OptionalDouble
Available reductions
On Stream<T> :
- reduce(), with different parameters
- count(), min(), max()
- anyMatch(), allMatch(), noneMatch()
- findFirst(), findAny()
- toArray()
- forEach(), forEachOrdered()
Available reductions
On IntStream, LongStream, DoubleStream :
- average()
- summaryStatistics()
Mutable reductions
Mutable reductions : example 1
Use of the helper class : Collectors
ArrayList<String> strings =
stream
.map(Object::toString)
.collect(Collectors.toList()) ;
Mutable reductions : example 2
Concatenating strings with a helper
String names = persons
.stream()
.map(Person::getName)
.collect(Collectors.joining()) ;
Mutable reductions
Common things :
- have a container : Collection or StringBuilder
- have a way to add an element to the container
- have a way to merge two containers (for parallelization)
Mutable reductions : example 1
Putting things together :
ArrayList<String> strings =
stream
.map(Object::toString)
.collect(
() -> new ArrayList<String>(), // the supplier
(suppliedList, s) -> suppliedList.add(s), // the accumulator
(supplied1, supplied2) -> supplied1.addAll(supplied2) // the combiner
) ;
Mutable reductions : example 1
Putting things together :
ArrayList<String> strings =
stream
.map(Object::toString)
.collect(
ArrayList::new, // the supplier
ArrayList::add, // the accumulator
ArrayList::addAll // the combiner
) ;
Mutable reductions : example 1
Putting things together :
ArrayList<String> strings =
stream
.map(Object::toString)
.collect(
ArrayList::new, // the supplier
ArrayList::add, // the accumulator
ArrayList::addAll // the combiner
) ;
ArrayList<String> strings =
stream
.map(Object::toString)
.collect(Collectors.toList()) ;
Collectors
The Collectors class
A rich toolbox (37 methods) for various types of reductions
- counting, minBy, maxBy
- summing, averaging, summarizing
- joining
- toList, toSet
And
- mapping, groupingBy, partionningBy
The Collectors class
Average, Sum, Count
persons
.stream()
.collect(Collectors.averagingDouble(Person::getAge)) ;
persons
.stream()
.collect(Collectors.counting()) ;
The Collectors class
Concatenating the names in a String
String names = persons
.stream()
.map(Person::getName)
.collect(Collectors.joining(", ")) ;
The Collectors class
Accumulating in a List, Set
Set<Person> setOfPersons = persons
.stream()
.collect(
Collectors.toSet()) ;
The Collectors class
Accumulating in a custom collection
TreeSet<Person> treeSetOfPersons = persons
.stream()
.collect(
Collectors.toCollection(TreeSet::new)) ;
The Collectors class
Getting the max according to a comparator
Bonus : new API to build comparators
Optional<Person> optionalPerson = persons
.stream()
.collect(
Collectors.maxBy(
Comparator.comparing(Person::getAge)) ;
Building comparators
New API to build comparators in a declarative way
Comparator<Person> comp =
Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
.thenComparing(Person:getAge) ;
Other examples
Interface Predicate
Predicate<Long> p1 = i -> i > 20 ;
Predicate<Long> p2 = i -> i < 50 ;
Predicate<Long> p3 = p1.and(p2) ;
Person stephan = ... ;
Predicate<Person> p = Predicat.isEqual(stephan) ;
The Collector API : groupingBy
« Grouping by » builds hash maps
- must explain how the keys are built
- by default the values are put in a list
- may specify a downstream (ie a collector)
The Collector API : groupingBy
Grouping a list of persons by their age
Map<Integer, List<Person>> map =
persons
.stream()
.collect(
Collectors.groupingBy(Person::getAge)) ;
The Collector API : groupingBy
Grouping a list of persons by their age
Map<Integer, Set<Person>> map =
persons
.stream()
.collect(
Collectors.groupingBy(
Person::getAge,
Collectors.toSet() // the downstream
) ;
The Collector API : groupingBy
Grouping a list of persons names by their age
Map<Integer, Set<String>> map =
persons
.stream()
.collect(
Collectors.groupingBy(
Person::getAge,
Collectors.mapping( //
Person::getLastName, // the downstream
Collectors.toSet() //
)
) ;
The Collector API : groupingBy
Grouping a list of persons names by their age
Map<Integer, TreeSet<String>> map =
persons
.stream()
.collect(
Collectors.groupingBy(
Person::getAge,
Collectors.mapping(
Person::getLastName,
Collectors.toCollection(TreeSet::new)
)
) ;
The Collector API : groupingBy
Grouping a list of blah blah blah
TreeMap<Integer, TreeSet<String>> map =
persons
.stream()
.collect(
Collectors.groupingBy(
Person::getAge,
TreeMap::new,
Collectors.mapping(
Person::getLastName,
Collectors.toCollection(TreeSet::new)
)
) ;
The Collector API : groupingBy
Example : creating an age histogram
Gives the # of persons by age
Map<Integer, Long> map =
persons
.stream()
.collect(
Collectors.groupingBy(Person::getAge, Collectors.counting())
) ;
The Collectors class : mapping
The mapping helper method takes 2 parameter :
- a function, that maps the elements of the stream
- a collector, called a « downstream », that is applied to
the mapped values
The Collectors class : mapping
Accumulating names in a set
Set<String> set = persons
.stream()
.collect(
Collectors.mapping(
Person::getLastName,
Collectors.toSet())) ;
The Collectors class : mapping
Mapping the stream, then accumulating in a collection
TreeSet<String> set = persons
.stream()
.collect(
Collectors.mapping(
Person::getLastName,
Collectors.toCollection(TreeSet::new))
) ;
The Collector API : partioningBy
Creates a Map<Boolean, …> on a predicate
- the map has 2 keys : TRUE and FALSE
- may specify a downstream
The Collector API : partioningBy
Creates a Map<Boolean, …> on a predicate
map.get(TRUE) returns the list people older than 20
Map<Boolean, List<Person>> map =
persons
.stream()
.collect(
Collectors.partitioningBy(p -> p.getAge() > 20)
) ;
The Collector API : partioningBy
Can further process the list of persons
Map<Boolean, TreeSet<String>> map =
persons
.stream()
.collect(
Collectors.partitioningBy(
p -> p.getAge() > 20,
Collectors.mapping(
Person::getLastName,
Collectors.toCollection(TreeSet::new))
)
)
) ;
The Collector API : partioningBy
Can further process the list of persons
Map<Boolean, TreeSet<String>> map =
persons
.stream()
.collect(
Collectors.partitioningBy(
p -> p.getAge() > 20,
Collectors.mapping(
Person::getLastName,
Collectors.toCollection(TreeSet::new))
)
)
) ;
Partition the persons
on age > 20
The Collector API : partioningBy
Can further process the list of persons
Map<Boolean, TreeSet<String>> map =
persons
.stream()
.collect(
Collectors.partitioningBy(
p -> p.getAge() > 20,
Collectors.mapping(
Person::getLastName,
Collectors.toCollection(TreeSet::new))
)
)
) ;
Gather their names…
The Collector API : partioningBy
Can further process the list of persons
Map<Boolean, TreeSet<String>> map =
persons
.stream()
.collect(
Collectors.partitioningBy(
p -> p.getAge() > 20,
Collectors.mapping(
Person::getLastName,
Collectors.toCollection(TreeSet::new))
)
)
) ;
… in TreeSets
The Collector API : collectingAndThen
Collect data with a downstream
Then apply a function called a « finisher »
Useful for putting the result in a immutable collection
The Collector API : collectingAndThen
In this case « Map::entrySet » is a finisher
Set<Map.Entry<Integer, List<Person>>> set =
persons
.stream()
.collect(
Collectors.collectingAndThen(
Collectors.groupingBy(
Person::getAge), // downstream, builds a map
Map::entrySet // finisher, applied on the map
) ;
Some real examples
1st example
Optional<Entry<Integer, Long>> opt =
movies.stream().parallel()
.collect(
Collectors.collectingAndThen(
Collectors.groupingBy(
movie -> movie.releaseYear(),
Collectors.counting()
),
Map::entrySet
)
)
.stream()
.max(Map.Entry.comparingByValue()) ;
1st example
Optional<Entry<Integer, Long>> opt =
movies.stream().parallel()
.collect(
Collectors.collectingAndThen(
Collectors.groupingBy(
movie -> movie.releaseYear(),
Collectors.counting()
),
Map::entrySet
)
)
.stream()
.max(Map.Entry.comparingByValue()) ;
A Stream of movies
1st example
Optional<Entry<Integer, Long>> opt =
movies.stream().parallel()
.collect(
Collectors.collectingAndThen(
Collectors.groupingBy(
movie -> movie.releaseYear(),
Collectors.counting()
),
Map::entrySet
)
)
.stream()
.max(Map.Entry.comparingByValue()) ;
Building a map
of year / # of movies
1st example
Optional<Entry<Integer, Long>> opt =
movies.stream().parallel()
.collect(
Collectors.collectingAndThen(
Collectors.groupingBy(
movie -> movie.releaseYear(),
Collectors.counting()
),
Map::entrySet
)
)
.stream()
.max(Map.Entry.comparingByValue()) ;
Then getting the
entry set
1st example
Optional<Entry<Integer, Long>> opt =
movies.stream().parallel()
.collect(
Collectors.collectingAndThen(
Collectors.groupingBy(
movie -> movie.releaseYear(),
Collectors.counting()
),
Map::entrySet
)
)
.stream()
.max(Map.Entry.comparingByValue()) ;
Then getting the
max by value
1st example
Optional<Entry<Integer, Long>> opt =
movies.stream().parallel()
.collect(
Collectors.collectingAndThen(
Collectors.groupingBy(
movie -> movie.releaseYear(),
Collectors.counting()
),
Map::entrySet
)
)
.stream()
.max(Map.Entry.comparingByValue()) ;
Returns the
year with the most
movies released
Conclusion
Conclusion
Why are lambdas introduced in Java 8 ?
Conclusion
Why are lambdas introduced in Java 8 ?
Because it’s in the mood !
Conclusion
Why are lambdas introduced in Java 8 ?
Because it’s in the mood !
Conclusion
Why are lambdas introduced in Java 8 ?
Because it’s in the mood !
Because it allows to write more compact code !
Compact code is better !
An example of compact code (in C)
#include "stdio.h"
main() {
int b=0,c=0,q=60,_=q;for(float i=-20,o,O=0,l=0,j,p;j=O*O,p=l*l,
(!_--|(j+p>4)?fputc(b?q+(_/3):10,(i+=!b,p=j=O=l=0,c++,stdout)),
_=q:l=2*O*l+i/20,O=j-p+o),b=c%q,c<2400;o=-2+b*.05) ;
}
http://www.codeproject.com/Articles/2228/Obfuscating-your-Mandelbrot-code
Compact code is better !
An example of compact code (in C)
#include "stdio.h"
main() {
int b=0,c=0,q=60,_=q;for(float i=-20,o,O=0,l=0,j,p;j=O*O,p=l*l,
(!_--|(j+p>4)?fputc(b?q+(_/3):10,(i+=!b,p=j=O=l=0,c++,stdout)),
_=q:l=2*O*l+i/20,O=j-p+o),b=c%q,c<2400;o=-2+b*.05) ;
}
http://www.codeproject.com/Articles/2228/Obfuscating-your-Mandelbrot-code
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++
++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++
++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++
++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++ ++ +++++++++++
+++++++++++++++++++++++++++++++++++ +++++++
++++++++++++++++++++++++++++++++++++ +++++++
+++++++++++++++++++++++++++++++++++ ++++++++
++++++++++++++++++++++++++++++++++ +++++++
+++++++++++++++++++++++++++++++++ +++++
+++++++++++++++++++++++++++++++++ ++++++
+++++++++++++++++++++++ + +++++ ++++++
+++++++++++++++++++++++ ++ ++++++
++++++++++++++++++++++ + ++++++
++++++++++++++++++++++ + ++++++
++++++++++++++++++++ + + +++++++
++++++ ++++++++
++++++++++++++++++++ + + +++++++
++++++++++++++++++++++ + ++++++
++++++++++++++++++++++ + ++++++
+++++++++++++++++++++++ ++ ++++++
+++++++++++++++++++++++ + +++++ ++++++
+++++++++++++++++++++++++++++++++ ++++++
+++++++++++++++++++++++++++++++++ +++++
++++++++++++++++++++++++++++++++++ +++++++
+++++++++++++++++++++++++++++++++++ ++++++++
++++++++++++++++++++++++++++++++++++ +++++++
+++++++++++++++++++++++++++++++++++ +++++++
++++++++++++++++++++++++++++++++++++ ++ +++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++
++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++
++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Conclusion
Why are lambdas introduced in Java 8 ?
Because it’s in the mood !
Because it allows to write more compact code !
Conclusion
Why are lambdas introduced in Java 8 ?
Because it brings new and efficient patterns,
that enable easy and safe parallelization,
- needed by modern applications
- needed by API writers
Conclusion
Java 8 is coming, it’s the biggest update in 15 years
Conclusion
Java 8 is coming, it’s the biggest update in 15 years
Moving to Java 8 means a lot of work for us developers !
- Self training
- Changing our habits
Conclusion
Java 8 is coming, it’s the biggest update in 15 years
Moving to Java 8 means a lot of work for us developers !
- Self training
- Changing our habits
- Convincing our bosses (sigh…)
Conclusion
Java 8 is coming, it’s the biggest update in 15 years
Release date : 18th march 2014 !
Conclusion
Java 8 is coming, it’s the biggest update in 15 years
« Java is a blue collar language. It’s not PhD thesis
material but a language for a job » – James Gosling, 1997
Conclusion
Java 8 is coming, it’s the biggest update in 15 years
« Language features are not a goal unto themselves;
language features are enablers, encouraging or
discouraging certain styles and idioms » – Brian Goetz,
2013
Conclusion
Java 8 is coming, it’s the biggest update in 15 years
The good news is :
Java is still Java !
Java 8 Streams & Collectors : the Leuven edition
Java 8 Streams & Collectors : the Leuven edition

Weitere ähnliche Inhalte

Was ist angesagt?

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
 
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
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2José Paumard
 
JFokus 50 new things with java 8
JFokus 50 new things with java 8JFokus 50 new things with java 8
JFokus 50 new things with java 8José 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
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé 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
 
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
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé Paumard
 
Ast transformations
Ast transformationsAst transformations
Ast transformationsHamletDRC
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full storyJosé Paumard
 
AST Transformations
AST TransformationsAST Transformations
AST TransformationsHamletDRC
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahNick Plante
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesGanesh Samarthyam
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardMario Fusco
 
C# 7.0 Hacks and Features
C# 7.0 Hacks and FeaturesC# 7.0 Hacks and Features
C# 7.0 Hacks and FeaturesAbhishek Sur
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performanceintelliyole
 

Was ist angesagt? (20)

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
 
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
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
JFokus 50 new things with java 8
JFokus 50 new things with java 8JFokus 50 new things with java 8
JFokus 50 new things with java 8
 
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
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
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
 
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
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full story
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and Pindah
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java Bytecodes
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
 
Java Class Design
Java Class DesignJava Class Design
Java Class Design
 
C# 7.0 Hacks and Features
C# 7.0 Hacks and FeaturesC# 7.0 Hacks and Features
C# 7.0 Hacks and Features
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performance
 
What's New In C# 7
What's New In C# 7What's New In C# 7
What's New In C# 7
 
C# 7
C# 7C# 7
C# 7
 

Ähnlich wie Java 8 Streams & Collectors : the Leuven edition

Autumn collections : from iterable to lambdas, streams and collectors
Autumn collections : from iterable to lambdas, streams and collectorsAutumn collections : from iterable to lambdas, streams and collectors
Autumn collections : from iterable to lambdas, streams and collectorsJosé Paumard
 
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguajeKotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguajeVíctor Leonel Orozco López
 
R getting spatial
R getting spatialR getting spatial
R getting spatialFAO
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2goMoriyoshi Koizumi
 
ACADILD:: HADOOP LESSON
ACADILD:: HADOOP LESSON ACADILD:: HADOOP LESSON
ACADILD:: HADOOP LESSON Padma shree. T
 
Mapfilterreducepresentation
MapfilterreducepresentationMapfilterreducepresentation
MapfilterreducepresentationManjuKumara GH
 
New features in jdk8 iti
New features in jdk8 itiNew features in jdk8 iti
New features in jdk8 itiAhmed mar3y
 
Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced Flink Forward
 
Java 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually useJava 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually useSharon Rozinsky
 
10. Getting Spatial
10. Getting Spatial10. Getting Spatial
10. Getting SpatialFAO
 
Apache pig presentation_siddharth_mathur
Apache pig presentation_siddharth_mathurApache pig presentation_siddharth_mathur
Apache pig presentation_siddharth_mathurSiddharth Mathur
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs偉格 高
 
Transformations and actions a visual guide training
Transformations and actions a visual guide trainingTransformations and actions a visual guide training
Transformations and actions a visual guide trainingSpark Summit
 

Ähnlich wie Java 8 Streams & Collectors : the Leuven edition (20)

Autumn collections : from iterable to lambdas, streams and collectors
Autumn collections : from iterable to lambdas, streams and collectorsAutumn collections : from iterable to lambdas, streams and collectors
Autumn collections : from iterable to lambdas, streams and collectors
 
Java 8 revealed
Java 8 revealedJava 8 revealed
Java 8 revealed
 
Java 8 by example!
Java 8 by example!Java 8 by example!
Java 8 by example!
 
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguajeKotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
 
R getting spatial
R getting spatialR getting spatial
R getting spatial
 
10. R getting spatial
10.  R getting spatial10.  R getting spatial
10. R getting spatial
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
 
4.1-Pig.pptx
4.1-Pig.pptx4.1-Pig.pptx
4.1-Pig.pptx
 
Lec_4_1_IntrotoPIG.pptx
Lec_4_1_IntrotoPIG.pptxLec_4_1_IntrotoPIG.pptx
Lec_4_1_IntrotoPIG.pptx
 
Functional Programming
Functional ProgrammingFunctional Programming
Functional Programming
 
MapReduce
MapReduceMapReduce
MapReduce
 
ACADILD:: HADOOP LESSON
ACADILD:: HADOOP LESSON ACADILD:: HADOOP LESSON
ACADILD:: HADOOP LESSON
 
Mapfilterreducepresentation
MapfilterreducepresentationMapfilterreducepresentation
Mapfilterreducepresentation
 
New features in jdk8 iti
New features in jdk8 itiNew features in jdk8 iti
New features in jdk8 iti
 
Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced
 
Java 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually useJava 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually use
 
10. Getting Spatial
10. Getting Spatial10. Getting Spatial
10. Getting Spatial
 
Apache pig presentation_siddharth_mathur
Apache pig presentation_siddharth_mathurApache pig presentation_siddharth_mathur
Apache pig presentation_siddharth_mathur
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
 
Transformations and actions a visual guide training
Transformations and actions a visual guide trainingTransformations and actions a visual guide training
Transformations and actions a visual guide training
 

Mehr von 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
 
Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKJosé 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
 
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
 
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
 
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
 
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
 
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
 
API Asynchrones en Java 8
API Asynchrones en Java 8API Asynchrones en Java 8
API Asynchrones en Java 8José Paumard
 

Mehr von José Paumard (16)

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
 
Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UK
 
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
 
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!
 
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
 
Streams in the wild
Streams in the wildStreams in the wild
Streams in the wild
 
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
 
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
 
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
 
API Asynchrones en Java 8
API Asynchrones en Java 8API Asynchrones en Java 8
API Asynchrones en Java 8
 

Kürzlich hochgeladen

Transaction Management in Database Management System
Transaction Management in Database Management SystemTransaction Management in Database Management System
Transaction Management in Database Management SystemChristalin Nelson
 
Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxthorishapillay1
 
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
 
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
 
Karra SKD Conference Presentation Revised.pptx
Karra SKD Conference Presentation Revised.pptxKarra SKD Conference Presentation Revised.pptx
Karra SKD Conference Presentation Revised.pptxAshokKarra1
 
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
FILIPINO PSYCHology sikolohiyang pilipino
FILIPINO PSYCHology sikolohiyang pilipinoFILIPINO PSYCHology sikolohiyang pilipino
FILIPINO PSYCHology sikolohiyang pilipinojohnmickonozaleda
 
Procuring digital preservation CAN be quick and painless with our new dynamic...
Procuring digital preservation CAN be quick and painless with our new dynamic...Procuring digital preservation CAN be quick and painless with our new dynamic...
Procuring digital preservation CAN be quick and painless with our new dynamic...Jisc
 
4.18.24 Movement Legacies, Reflection, and Review.pptx
4.18.24 Movement Legacies, Reflection, and Review.pptx4.18.24 Movement Legacies, Reflection, and Review.pptx
4.18.24 Movement Legacies, Reflection, and Review.pptxmary850239
 
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)lakshayb543
 
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptxMULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptxAnupkumar Sharma
 
Grade 9 Quarter 4 Dll Grade 9 Quarter 4 DLL.pdf
Grade 9 Quarter 4 Dll Grade 9 Quarter 4 DLL.pdfGrade 9 Quarter 4 Dll Grade 9 Quarter 4 DLL.pdf
Grade 9 Quarter 4 Dll Grade 9 Quarter 4 DLL.pdfJemuel Francisco
 
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptxINTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptxHumphrey A Beña
 
4.16.24 21st Century Movements for Black Lives.pptx
4.16.24 21st Century Movements for Black Lives.pptx4.16.24 21st Century Movements for Black Lives.pptx
4.16.24 21st Century Movements for Black Lives.pptxmary850239
 
Choosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for ParentsChoosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for Parentsnavabharathschool99
 
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
 
Concurrency Control in Database Management system
Concurrency Control in Database Management systemConcurrency Control in Database Management system
Concurrency Control in Database Management systemChristalin Nelson
 

Kürzlich hochgeladen (20)

Transaction Management in Database Management System
Transaction Management in Database Management SystemTransaction Management in Database Management System
Transaction Management in Database Management System
 
Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.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
 
YOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptx
YOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptxYOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptx
YOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_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
 
Karra SKD Conference Presentation Revised.pptx
Karra SKD Conference Presentation Revised.pptxKarra SKD Conference Presentation Revised.pptx
Karra SKD Conference Presentation Revised.pptx
 
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
 
FINALS_OF_LEFT_ON_C'N_EL_DORADO_2024.pptx
FINALS_OF_LEFT_ON_C'N_EL_DORADO_2024.pptxFINALS_OF_LEFT_ON_C'N_EL_DORADO_2024.pptx
FINALS_OF_LEFT_ON_C'N_EL_DORADO_2024.pptx
 
FILIPINO PSYCHology sikolohiyang pilipino
FILIPINO PSYCHology sikolohiyang pilipinoFILIPINO PSYCHology sikolohiyang pilipino
FILIPINO PSYCHology sikolohiyang pilipino
 
Procuring digital preservation CAN be quick and painless with our new dynamic...
Procuring digital preservation CAN be quick and painless with our new dynamic...Procuring digital preservation CAN be quick and painless with our new dynamic...
Procuring digital preservation CAN be quick and painless with our new dynamic...
 
4.18.24 Movement Legacies, Reflection, and Review.pptx
4.18.24 Movement Legacies, Reflection, and Review.pptx4.18.24 Movement Legacies, Reflection, and Review.pptx
4.18.24 Movement Legacies, Reflection, and Review.pptx
 
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
 
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptxMULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
 
Grade 9 Quarter 4 Dll Grade 9 Quarter 4 DLL.pdf
Grade 9 Quarter 4 Dll Grade 9 Quarter 4 DLL.pdfGrade 9 Quarter 4 Dll Grade 9 Quarter 4 DLL.pdf
Grade 9 Quarter 4 Dll Grade 9 Quarter 4 DLL.pdf
 
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptxINTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
 
4.16.24 21st Century Movements for Black Lives.pptx
4.16.24 21st Century Movements for Black Lives.pptx4.16.24 21st Century Movements for Black Lives.pptx
4.16.24 21st Century Movements for Black Lives.pptx
 
Choosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for ParentsChoosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for Parents
 
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
 
Concurrency Control in Database Management system
Concurrency Control in Database Management systemConcurrency Control in Database Management system
Concurrency Control in Database Management system
 

Java 8 Streams & Collectors : the Leuven edition

  • 1. JDK 8 & Lambdas Lambdas, Streams & Collectors
  • 3. @JosePaumard Why were they introduced ? How will they change the way we build applications ?
  • 6. @JosePaumard In stock. Ships from and sold by Amazon.com. Gift-wrap available. Publisher: Addison-Wesley Professional; 1 edition November 10, 1994
  • 11. Let’s introduce the lambdas on a simple example
  • 12. A very simple example public class Person { private String name ; private int age ; // constructors // getters / setters } List<Person> list = new ArrayList<>() ; A plain old bean… … and a good old list
  • 13. int sum = 0 ; // I need a default value in case // the list is empty int average = 0 ; for (Person person : list) { sum += person.getAge() ; } if (!list.isEmpty()) { average = sum / list.size() ; } Average of the ages
  • 14. int sum = 0 ; int n = 0 ; int average = 0 ; for (Person person : list) { if (person.getAge() > 20) { n++ ; sum += person.getAge() ; } } if (n > 0) { average = sum / n ; } Trickier : average of the ages of people older than 20
  • 15. Trickier : average of the ages of people older than 20 « imperative programming » int sum = 0 ; int n = 0 ; int average = 0 ; for (Person person : list) { if (person.getAge() > 20) { n++ ; sum += person.getAge() ; } } if (n > 0) { average = sum / n ; }
  • 16. select avg(age) from Person where age > 20 … it does not have to be like that ! This is a description of the result
  • 17. select avg(age) from Person where age > 20 … it does not have to be like that ! This is a description of the result In that case, the DB server is free to compute the result the way it sees fit © SQL language, 1974
  • 18. Person age age > 20 sum 1st step : mapping map
  • 19. Person age age > 20 sum 1st step : mapping Mapping : - takes a list of a given type - gives another list of a different type - same number of elements map
  • 20. Person age age > 20 sum 2nd step : filtering filtermap
  • 21. Person age age > 20 sum 2nd step : filtering Filtering : - takes a list of a given type - gives another list of a the same type - less elements filtermap
  • 22. Person age age > 20 sum 3rd step : reduction reducefiltermap
  • 23. Person age age > 20 sum 3rd step : reduction Reduction : agregation of all the elements in a single one Ex : average, sum, min, max, etc… reducefiltermap
  • 24. How can I model that ?
  • 25. The JDK 7 way Create an interface to model the mapper… public interface Mapper<T, V> { public V map(T t) ; }
  • 26. public class PersonToAgeMapper implements Mapper<Person, Integer> { public Integer map(Person p) { return p.getAge() ; } } The JDK 7 way … and create an implementation … public interface Mapper<T, V> { public V map(T t) ; }
  • 27. Mapper<Person, Integer> mapper = new Mapper<Person, Integer>() { public Integer map(Person p) { return p.getAge() ; } } The JDK 7 way … that could be anonymous public interface Mapper<T, V> { public V map(T t) ; }
  • 28. The JDK 7 way We can do the same for the filtering public interface Predicate<T> { public boolean filter(T t) ; }
  • 29. public class AgePredicate implements Predicate<Integer> { public boolean filter(Integer i) { return i > 20 ; } } The JDK 7 way We can do the same for the filtering public interface Predicate<T> { public boolean filter(T t) ; }
  • 30. AgePredicate predicate = new Predicate<Integer>() { public boolean filter(Integer i) { return i > 20 ; } } The JDK 7 way We can do the same for the filtering public interface Predicate<T> { public boolean filter(T t) ; }
  • 31. The JDK 7 way And for the reduction public interface Reducer<T> { public T reduce(T t1, T t2) ; }
  • 32. public class Sum implements Reducer<Integer> { public Integer reduce(Integer i1, Integer i2) { return i1 + i2 ; } } The JDK 7 way And for the reduction public interface Reducer<T> { public T reduce(T t1, T t2) ; }
  • 33. Reducer<Integer> reduction = new Reducer<Integer>() { public Integer reduce(Integer i1, Integer i2) { return i1 + i2 ; } } The JDK 7 way And for the reduction public interface Reducer<T> { public T reduce(T t1, T t2) ; }
  • 34. The JDK 7 way So the whole map / filter / reduce looks like this 1) Create 3 interfaces public interface Mapper<T, V> { public V map(T t) ; } public interface Predicate<T> { public boolean filter(T t) ; } public interface Reducer<T> { public T reduce(T t1, T t2) ; }
  • 35. The JDK 7 way So the whole map / filter / reduce looks like this 1) Create 3 interfaces 2) Apply the pattern List<Person> persons = ... ; int sum = persons.map( new Mapper<Person, Integer>() { public Integer map(Person p) { return p.getAge() ; } }) .filter( new Filter<Integer>() { public boolean filter(Integer age) { return age > 20 ; } }) .reduce(0, new Reducer<Integer>() { public Integer recude(Integer i1, Integer i2) { return i1 + i2 ; } } }) ;
  • 36. The JDK 7 way So the whole map / filter / reduce looks like this 1) Create 3 interfaces 2) Apply the pattern List<Person> persons = ... ; int sum = persons.map( new Mapper<Person, Integer>() { public Integer map(Person p) { return p.getAge() ; } }) .filter( new Filter<Integer>() { public boolean filter(Integer age) { return age > 20 ; } }) .reduce(0, new Reducer<Integer>() { public Integer recude(Integer i1, Integer i2) { return i1 + i2 ; } } }) ;
  • 37. The JDK 8 way
  • 38. mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { return person.getAge() ; } } The JDK 8 way Let’s rewrite our mapper
  • 39. mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } } The JDK 8 way Let’s rewrite our mapper
  • 40. mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return p.getAge() ; } } The JDK 8 way mapper = (Person person) ; we take a person p Let’s rewrite our mapper
  • 41. mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } } The JDK 8 way mapper = (Person person) -> ; and then … Let’s rewrite our mapper
  • 42. mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } } The JDK 8 way mapper = (Person person) -> person.getAge() ; … return the age of p Let’s rewrite our mapper
  • 43. Let’s rewrite our mapper mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } } The JDK 8 way mapper = (Person person) -> person.getAge() ;
  • 44. Let’s rewrite our mapper The compiler can recognize this as an implementation of Mapper mapper = new Mapper<Person, Integer>() { public Integer map(Person person) { // 1 method return person.getAge() ; } } The JDK 8 way mapper = (Person person) -> person.getAge() ;
  • 45. What if … … there is more than one statement ? The return has to be explicit mapper = Person person -> { System.out.println("Mapping " + person) ; return person.getAge() ; }
  • 46. What if … …I have no return value ? consumer = Person person -> p.setAge(p.getAge() + 1) ;
  • 47. What if … …I have more than one argument ? Or : reducer = (int i1, int i2) -> { return i1 + i2 ; } reducer = (int i1, int i2) -> i1 + i2 ;
  • 48. The JDK 8 way How can the compiler recognize the implementation of map() ? mapper = (Person person) -> person.getAge() ;
  • 49. The JDK 8 way How can the compiler recognize the implementation of map() ? 1) There’s only one method in Mapper mapper = (Person person) -> person.getAge() ;
  • 50. The JDK 8 way How can the compiler recognize the implementation of map() ? 1) There’s only one method in Mapper 2) Both the parameters and the return types are compatible mapper = (Person person) -> person.getAge() ;
  • 51. The JDK 8 way How can the compiler recognize the implementation of map() ? 1) There’s only one method in Mapper 2) Both the parameters and the return types are compatible 3) Thrown exceptions (if any) are compatible mapper = (Person person) -> person.getAge() ;
  • 52. More lambdas Writing more lambdas becomes natural : mapper = (Person person) -> person.getAge() ; // mapper filter = (int age) -> age > 20 ; // filter reducer = (int i1, int i2) -> i1 + i2 ; // reducer
  • 53. More lambdas And most of the time, the compiler understands this : The « parameter types » can be omitted mapper = person -> person.getAge() ; // mapper filter = age -> age > 20 ; // filter reducer = (i1, i2) -> i1 + i2 ; // reducer
  • 54. Just a remark on the reduction How does it really work ?
  • 64. Reduction 2 examples : Caveat : the result is always reproductible in serial it’s not in parallel Reducer r1 = (i1, i2) -> i1 + i2 ; // Ok Reducer r2 = (i1, i2) -> i1*i1 + i2*i2 ; // Oooops
  • 65. So far A lambda expression is an alternative to write instances of anonymous inner classes
  • 66. Other syntaxes Very often one writes This syntax is also possible : mapper = person -> person.getAge() ; mapper = Person::getAge ; // non static method
  • 67. Other syntaxes Other example : Or : sum = (i1, i2) -> i1 + i2 ; sum = Integer::sum ; // static method, new ! max = (i1, i2) -> i1 > i2 ? i1 : i2 ; max = Integer::max ; // static method, new !
  • 68. Other syntaxes Other example : toLower = String::toLowerCase ; // !!!! NO NO NO !!!! toLowerFR = String::toLowerCase(Locale.FRANCE) ;
  • 69. More on the lambdas
  • 70. Questions : What model for a lambda ?
  • 71. Questions : What model for a lambda ? Can I put a lambda in a variable ?
  • 72. Questions : What model for a lambda ? Can I put a lambda in a variable ? Is a lambda an object ?
  • 73. Modelization A lambda is an instance of a « functional interface » @FunctionalInterface public interface Consumer<T> { public void accept(T t) ; }
  • 74. Modelization A lambda is an instance of a « functional interface » - only one abstract method (methods from Object dont count) - can be annotated by @FunctionalInterface (optional) @FunctionalInterface public interface Consumer<T> { public void accept(T t) ; }
  • 75. Putting a lambda in a variable Example of a consumer So : Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ; Consumer<String> c = s -> System.out.println(s) ;
  • 76. Putting a lambda in a variable Example of a consumer So : Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ; Consumer<String> c = s -> System.out.println(s) ; Question : what is s ?
  • 77. Putting a lambda in a variable Example of a consumer So : Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ; Consumer<String> c = s -> System.out.println(s) ; Answer : the compiler infers that it is a String
  • 78. Putting a lambda in a variable Example of a consumer So : Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ; Consumer<String> c = System.out::println ;
  • 79. Questions : What model for a lambda ? answer : with a functional interface Can I put a lambda in a variable ? answer : yes Is a lambda an object ?
  • 80. Is a lambda an objet ? Let’s play the game of 7 errors (with only 1 error) Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ; Consumer<String> c = s -> System.out.println(s) ;
  • 81. Is a lambda an objet ? Let’s play the game of 7 errors (with only 1 error) Consumer<String> c = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s) ; } } ; Consumer<String> c = s -> System.out.println(s) ;
  • 82. Questions : What model for a lambda ? answer : with a functional interface Can I put a lambda in a variable ? answer : yes Is a lambda an object ? answer : no
  • 83. Plenty of lambdas : java.util.function
  • 84. Java.util.function This new package holds the functional interfaces There are 43 of them
  • 85. Java.util.function Supplier : alone in its kind Consumer / BiConsumer Function / BiFunction (UnaryOperator / BinaryOperator) Predicate / BiPredicate Plus the primitive types versions
  • 86. Supplier A supplier supplies an object public interface Supplier<T> { T get() ; }
  • 87. Consumer A consumer just … accepts an object public interface Consumer<T> { void accept(T t) ; } Consumer<String> c1 = s -> System.out.println(s) ; Consumer<String> c2 = ... ; Consumer<String> c3 = c1.andThen(c2) ; persons.stream().forEach(c3) ;
  • 88. Function A function takes an object and returns another one Can be chained and / or composed public interface Function<T, R> { R apply(T t) ; }
  • 89. Predicate A Predicate takes an object and returns a boolean Can be negated, composed with and / or public interface Predicate<T> { boolean test(T t) ; }
  • 90. Back to the map / filter / reduce pattern
  • 91. The JDK 7 way How to apply map / filter / reduce to List<Person> ?
  • 92. The JDK 7 way How to apply map / filter / reduce to List<Person> ? The legal way is to iterate over the elements and apply the pattern
  • 93. The JDK 7 way How to apply map / filter / reduce to List<Person> ? The legal way is to iterate over the elements and apply the pattern One can create a helper method
  • 94. Applying map to a List With a helper method, JDK 7 List<Person> persons = new ArrayList<>() ; List<Integer> ages = // ages is a new list Lists.map( persons, new Mapper<Person, Integer>() { public Integer map(Person p) { return p.getAge() ; } } ) ;
  • 95. Applying map to a List With a helper method, JDK 8 & lambdas List<Person> persons = new ArrayList<>() ; List<Integer> ages = Lists.map( persons, person -> person.getAge() ) ;
  • 96. Applying map to a List With a helper method, JDK 8 & lambdas List<Person> persons = new ArrayList<>() ; List<Integer> ages = Lists.map( persons, Person::getAge ) ;
  • 97. Putting things together The map / filter / reduce pattern would look like this // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
  • 98. Putting things together The map / filter / reduce pattern would look like this The idea is to push lambdas to the API, and let it apply them on its content // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
  • 99. Putting things together The map / filter / reduce pattern would look like this Pro : the API can be optimized without touching the code : great ! // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
  • 100. Putting things together The map / filter / reduce pattern would look like this Pro : the API can be optimized without touching the code Cons … // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
  • 101. Putting things together 1) Suppose persons is a really BIG list // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
  • 102. Putting things together 1) Suppose persons is a really BIG list 2 duplications : ages & agesGT20 // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
  • 103. Putting things together 1) Suppose persons is a really BIG list 2 duplications : ages & agesGT20 What do we do with them ? Send them to the GC // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
  • 104. Putting things together 2) Suppose we have a allMatch() reducer allMatch is true if all the names are shorter than 20 chars let’s see a possible implementation of allMatch() // applying the map / filter / reduce pattern List<Person> persons = ... ; List<String> names = Lists.map(persons, p -> p.getName()) ; boolean allMatch = Lists.allMatch(names, n -> n.length() < 20) ;
  • 105. How could one write allMatch ? Here is a basic implementation of allMatch public static <T> boolean allMatch( List<? extends T> list, Filter<T> filter) { for (T t : list) { if (!filter.filter(t)) { return false ; } } return true ; }
  • 106. How could one write allMatch ? Here is a basic implementation of allMatch public static <T> boolean allMatch( List<? extends T> list, Filter<T> filter) { for (T t : list) { if (!filter.filter(t)) { return false ; } } return true ; } No need to iterate over the whole list
  • 107. Putting things together When we apply the allMatch() reducer… … the list names has already been evaluated ! // applying the map / filter / reduce pattern List<Person> persons = ... ; List<String> names = Lists.map(persons, p -> p.getName()) ; boolean allMatch = Lists.allMatch(names, n.length() < 20) ;
  • 108. Putting things together When we apply the allMatch() reducer… … we should have wait to apply the filter A good way to do that : apply the filter step lazily ! // applying the map / filter / reduce pattern List<Person> persons = ... ; List<String> names = Lists.map(persons, p -> p.getName()) ; boolean allMatch = Lists.allMatch(names, n.length() < 20) ;
  • 109. Conclusion Pro : 1 Cons : 2 (at least) // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ;
  • 110. // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = Lists.map( persons, p -> p.getAge()) ; List<Integer> agesGT20 = Lists.filter(ages, a -> a > 20) ; int sum = Lists.reduce(agesGT20, (i1, i2) -> i1 + i2) ; Conclusion Pro : 1 Cons : 2 (at least)
  • 111. Conclusion And the same goes for this one // applying the map / filter / reduce pattern List<Person> persons = ... ; List<Integer> ages = persons.map(p -> p.getAge()) ; List<Integer> agesGT20 = ages.filter(a -> a > 20) ; int sum = agesGT20.reduce(ages, (i1, i2) -> i1 + i2) ;
  • 112. Conclusion (again) We need a new concept to handle BIG lists efficiently
  • 113. Conclusion (again) We need a new concept to handle BIG lists efficiently The Collection framework is not the right one…
  • 114. Conclusion (again) We need a new concept to handle BIG lists efficiently The Collection framework is not the right one We need something else !
  • 115. So what pattern to choose ?
  • 116. Introduction Putting map / filter / reduce methods on Collection would have led to : And even if it doesnt lead to viable patterns, it is still a pleasant way of writing things // map / filter / reduce pattern on collections int sum = persons .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;
  • 117. Introduction Let’s keep the same kind of pattern and add a stream() // map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;
  • 118. Introduction Collection.stream() returns a Stream : new interface New interface = our hands are free ! // map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;
  • 119. New Collection interface So we need a new method on Collection public interface Collection<E> { // our good old methods Stream<E> stream() ; }
  • 120. New Collection interface Problem : ArrayList doesnt compile anymore… Something has to be done ! public interface Collection<E> { // our good old methods Stream<E> stream() ; }
  • 121. Interfaces Problem : ArrayList doesnt compile anymore… Something has to be done ! Something that does not need to change or recompile all the existing implementations of Collection
  • 123. Java 8 interfaces Problem : how to add methods to an interface, without changing any of the implementations ?
  • 124. Java 8 interfaces Problem : how to add methods to an interface, without changing any of the implementations ? Solution : change the way interfaces work in Java
  • 125. Java 8 interfaces ArrayList needs to know the implementation of stream()… public interface Collection<E> { // our good old methods Stream<E> stream() ; }
  • 126. Java 8 interfaces Let’s put it in the interface ! public interface Collection<E> { // our good old methods default Stream<E> stream() { return ... ; } }
  • 127. Java 8 interfaces Let’s introduce default methods in Java Default methods are about interface evolution Allows the extension of old interfaces public interface Collection<E> { // our good old methods default Stream<E> stream() { return ... ; } }
  • 128. Default methods Does it bring multiple inheritance to Java ?
  • 129. Default methods Does it bring multiple inheritance to Java ? Yes ! But we already have it
  • 130. Default methods Does it bring multiple inheritance to Java ? Yes ! But we already have it public class String implements Serializable, Comparable<String>, CharSequence { // ... }
  • 131. Default methods What we have so far is multiple inheritance of type
  • 132. Default methods What we have so far is multiple inheritance of type What we get in Java 8 is multiple inheritance of behavior
  • 133. Default methods What we have so far is multiple inheritance of type What we get in Java 8 is multiple inheritance of behavior What we dont have is multiple inheritance of state
  • 134. Default methods What we have so far is multiple inheritance of type What we get in Java 8 is multiple inheritance of behavior What we dont have is multiple inheritance of state … and this is where the trouble is !
  • 135. Default methods Will we have conflicts ?
  • 136. Default methods Will we have conflicts ? Oooh yes…
  • 137. Default methods Will we have conflicts ? Oooh yes… So we need rules to handle them
  • 138. Default methods public class C implements A, B { // ... }
  • 139. Default methods public interface A { default String a() { ... } } public interface B { default String a() { ... } } Example #1 public class C implements A, B { // ... }
  • 140. Example #1 Compile error : class C inherits unrelated defaults for a() from types A and B Default methods public interface A { default String a() { ... } } public interface B { default String a() { ... } } public class C implements A, B { // ... }
  • 141. Example #2 Class wins ! Default methods public interface A { default String a() { ... } } public interface B { default String a() { ... } } public class C implements A, B { public String a() { ... } }
  • 142. Example #2a I can explicitly call a default implementation Default methods public interface A { default String a() { ... } } public interface B { default String a() { ... } } public class C implements A, B { public String a() { return B.super.a() ; } }
  • 143. Example #3 More specific interfaces wins over less specific Default methods public interface A extends B { default String a() { ... } } public interface B { default String a() { ... } } public class C implements A, B { // ... }
  • 144. 2 simple rules To handle the conflict of multiple inheritance of behavior
  • 145. 2 simple rules To handle the conflict of multiple inheritance of behavior 1) Class wins !
  • 146. 2 simple rules To handle the conflict of multiple inheritance of behavior 1) Class wins ! 2) More specific interfaces wins over less specific
  • 147. An example Everybody who writes an implementation of Iterator writes this : public class MyIterator implements Iterator<E> { // some critical business code public void remove() { throw new UnsupportedOperationException("You shouldnt do that") ; } ; }
  • 148. An example Thanks to Java 8 : No silly implementation of remove() anymore ! public interface Iterator<E> { default void remove() { throw new UnsupportedOperationException("remove") ; } ; }
  • 149. Java 8 interfaces So the concept of « interface » changed in Java 8 public class HelloWorld { // souvenir souvenir public static void main(String[] args) { System.out.println("Hello world!") ; } ; }
  • 150. Java 8 interfaces So the concept of « interface » changed in Java 8 I mean, really public interface HelloWorld { // souvenir souvenir public static void main(String[] args) { System.out.println("Hello world!") ; } ; }
  • 151. Java 8 interfaces 1) Default methods, multiple behavior inheritance Rules to handle conflicts, solved at compile time 2) Static methods in interfaces Will bring new patterns and new ways to write APIs
  • 152. Where are we ? 1) We have a new syntax 2) We have a new pattern to implement 3) We have new interfaces to keep the backward compatibily
  • 154. What is a Stream From a technical point of view : a typed interface « a stream of String »
  • 155. What is a Stream From a technical point of view : a typed interface Other classes for primitive types : « a stream of String » IntStream, LongStream, DoubleStream
  • 156. It’s a new notion 1) A stream doesnt hold any data It’s just an object on which one can declare operations Streams are about « specifying computations »
  • 157. It’s a new notion 1) A stream doesnt hold any data 2) A stream cant modify its source Consequence : it can use parallel processing
  • 158. It’s a new notion 1) A stream doesnt hold any data 2) A stream cant modify its source 3) A source can be infinite So we need a way to guarantee that computations will be conducted in finite time
  • 159. It’s a new notion 1) A stream doesnt hold any data 2) A stream cant modify its source 3) A source can be infinite 4) A stream works lazily Then optimizations can be made among the different operations We need a way / convention to trigger the computations
  • 160. How can we build a stream ? Many ways… 1) From a collection : method Collection.stream Collection<String> collection = ... ; Stream<String> stream = collection.stream() ;
  • 161. How can we build a stream ? Many ways… 1) From a collection : method Collection.stream 2) From an array : Arrays.stream(Object []) Stream<String> stream2 = Arrays.stream(new String [] {"one", "two", "three"}) ;
  • 162. How can we build a stream ? Many ways… 1) From a collection : method Collection.stream 2) From an array : Arrays.stream(Object []) 3) From factory methods in Stream, IntStream, … Stream<String> stream1 = Stream.of("one", "two", "three") ;
  • 163. How can we build a stream ? Some more patterns Stream.empty() ; // returns an empty Stream Stream.of(T t) ; // a stream with a single element Stream.generate(Supplier<T> s) ; Stream.iterate(T seed, UnaryOperator<T> f) ;
  • 164. How can we build a stream ? Other ways scattered in the JDK string.chars() ; // returns a IntStream lineNumberReader.lines() ; // returns a Stream<String> random.ints() ; // return a IntStream
  • 165. 3 points about Stream
  • 166. 1) Two types of operations One can declare operations on a Stream Two types of operations : 1) Intermediate operations : declarations, processed lazily ex : map, filter
  • 167. 1) Two types of operations One can declare operations on a Stream Two types of operations : 1) Intermediate operations : declarations, processed lazily ex : map, filter 2) Terminal operations : trigger the computations ex : reduce
  • 168. A 1st example Back to our map / filter / reduce example // map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ; Build a stream on a List
  • 169. A 1st example Back to our map / filter / reduce example // map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ; Declare operations
  • 170. A 1st example Back to our map / filter / reduce example // map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ; Triggers the computation
  • 171. 2) State of a stream The implementation of Stream has a state : - SIZED : the number of elements is known - ORDERED : the order matters (List) - DISTINCT : all elements are unique (Set) - SORTED : all elements have been sorted (SortedSet)
  • 172. 2) State of a stream Some operations change that : - filtering removes the SIZED - mapping removes DISTINCT and SORTED
  • 173. 2) State of a stream And it allows nice optimizations ! - a HashSet cant have doubles so…
  • 174. 2) State of a stream And it allows nice optimizations ! - a HashSet cant have doubles so… - distinct() is NOPed on a stream built on a HashSet
  • 175. 2) State of a stream And it allows nice optimizations ! - a HashSet cant have doubles so… - distinct() is NOPed on a stream built on a HashSet - A TreeSet is sorted so…
  • 176. 2) State of a stream And it allows nice optimizations ! - a HashSet cant have doubles so… - distinct() is NOPed on a stream built on a HashSet - A TreeSet is sorted so… - sorted() is NOPed on a stream built on a TreeSet
  • 177. 3) Stateless / stateful operations Stateless / stateful operations Some operations are stateless : It means that they dont need more information than the one held by their parameters persons.stream().map(p -> p.getAge()) ;
  • 178. 3) Stateless / stateful operations Stateless / stateful operations Some operations are stateless : Some need to retain information : persons.stream().map(p -> p.getAge()) ; stream.limit(10_000_000) ; // select the 10M first elements
  • 179. Example Let’s sort an array of String Random rand = new Random() ; String [] strings = new String[10_000_000] ; for (int i = 0 ; i < strings.length ; i++) { strings[i] = Long.toHexString(rand.nextLong()) ; }
  • 180. Example Let’s sort an array of String Soooo Java 7… Random rand = new Random() ; String [] strings = new String[10_000_000] ; for (int i = 0 ; i < strings.length ; i++) { strings[i] = Long.toHexString(rand.nextLong()) ; }
  • 181. Example Let’s sort an array of String Better ? Random rand = new Random() ; Stream<String> stream = Stream.generate( () -> Long.toHexString(rand.nextLong()) ) ;
  • 182. Example Let’s sort an array of String Better ! // Random rand = new Random() ; Stream<String> stream = Stream.generate( () -> Long.toHexString(ThreadLocalRandom.current().nextLong()) ) ;
  • 183. Example Let’s sort an array of String // other way Stream<String> stream = ThreadLocalRandom .current() .longs() // returns a LongStream .mapToObj(l -> Long.toHexString(l)) ;
  • 184. Example Let’s sort an array of String // other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) ;
  • 185. Example Let’s sort an array of String // other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) .limit(10_000_000) .sorted() ; T = 4 ms
  • 186. Example Let’s sort an array of String // other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) .limit(10_000_000) .sorted() ; Object [] sorted = stream.toArray() ;
  • 187. Example Let’s sort an array of String // other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) .limit(10_000_000) .sorted() ; Object [] sorted = stream.toArray() ; T = 14 s
  • 188. Example Let’s sort an array of String // other way Stream<String> stream = ThreadLocalRandom .current() .longs() .mapToObj(Long::toHexString) .limit(10_000_000) .sorted() ; Object [] sorted = stream.toArray() ; T = 14 s Intermediate calls !
  • 189. Last word about stream operations 1) There are intermediate and terminal operations 2) A stream is processed on a terminal operation call
  • 190. Last word about stream operations 1) There are intermediate and terminal operations 2) A stream is processed on a terminal operation call 3) Only one terminal operation is allowed 4) It cannot be processed again If needed another stream should be built on the source
  • 192. Optimization The first optimization (well, laziness was first !) we need is parallelism The fork / join enable parallel programming since JDK 7 But writing tasks is hard and does not always lead to better performances
  • 193. Optimization The first optimization (well, laziness was first !) we need is parallelism The fork / join enable parallel programming since JDK 7 But writing tasks is hard and does not always lead to better performances Using the parallel stream API is much more secure
  • 194. How to build a parallel stream ? Two patterns 1) Call parallelStream() instead of stream() 2) Call parallel() on an existing stream Stream<String> s = strings.parallelStream() ; Stream<String> s = strings.stream().parallel() ;
  • 195. Is parallelism really that simple ? Well… yes !
  • 196. Is parallelism really that simple ? Well… yes ! … and no
  • 197. Is parallelism really that simple ? Example 1 : « returns the 10M first elements of the source » persons.stream().limit(10_000_000) ;
  • 198. Is parallelism really that simple ? Example 1 : « returns the 10M first elements of the source » persons.parallelStream().limit(10_000_000) ;
  • 199. Is parallelism really that simple ? Example 1 : performances Code 1 List<Long> list = new ArrayList<>(10_000_100) ; for (int i = 0 ; i < 10_000_000 ; i++) { list1.add(ThreadLocalRandom.current().nextLong()) ; }
  • 200. Is parallelism really that simple ? Example 1 : performances Code 2 Stream<Long> stream = Stream.generate(() -> ThreadLocalRandom.current().nextLong()) ; List<Long> list1 = stream.limit(10_000_000).collect(Collectors.toList()) ;
  • 201. Is parallelism really that simple ? Example 1 : performances Code 3 Stream<Long> stream = ThreadLocalRandom.current().longs(10_000_000).mapToObj(Long::new) ; List<Long> list = stream.collect(Collectors.toList()) ;
  • 202. Is parallelism really that simple ? Example 1 : performances Serial Parallel Code 1 (for) 270 ms Code 2 (limit) 310 ms Code 3 (longs) 250 ms
  • 203. Is parallelism really that simple ? Example 1 : performances Serial Parallel Code 1 (for) 270 ms Code 2 (limit) 310 ms 500 ms Code 3 (longs) 250 ms 320 ms
  • 204. Is parallelism really that simple ? Example 2 : « returns a stream with all the elements of the first stream followed by all the elements of the second stream » Stream s3 = Stream.concat(stream1, stream2) ;
  • 205. Parallelism Parallelism implies overhead most of the time Badly configured parallel operations can lead to unneeded computations that will slow down the overall process Unnecessary ordering of a stream will lead to performance hits
  • 207. A simple reduction Sum of ages // map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .reduce(0, (a1, a2) -> a1 + a2) ;
  • 208. A simple reduction It would be nice to be able to write : But there’s no sum() on Stream<T> What would be the sense of « adding persons » ? // map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .sum() ;
  • 209. A simple reduction It would be nice to be able to write : But there’s no sum() on Stream<T> There’s one on IntStream ! // map / filter / reduce pattern on collections int sum = persons.stream() .map(p -> p.getAge()) .filter(a -> a > 20) .sum() ;
  • 210. A simple reduction 2nd version : Value if persons is an empty list : 0 // map / filter / reduce pattern on collections int sum = persons.stream() .map(Person::getAge) .filter(a -> a > 20) .mapToInt(Integer::intValue) .sum() ;
  • 211. A simple reduction 2nd version (even better) : Value if persons is an empty list : 0 // map / filter / reduce pattern on collections int sum = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) // .mapToInt(Integer::intValue) .sum() ;
  • 212. A simple reduction What about max() and min() ? How can one chose a default value ? // map / filter / reduce pattern on collections ....... = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) .max() ;
  • 213. Problem with the default value The « default value » is a tricky notion
  • 214. Problem with the default value The « default value » is a tricky notion 1) The « default value » is the reduction of the empty set
  • 215. Problem with the default value The « default value » is a tricky notion 1) The « default value » is the reduction of the empty set 2) But it’s also the identity element for the reduction
  • 224. Problem with the default value The « default value » is a tricky notion 1) The « default value » is the reduction of the empty set 2) But it’s also the identity element for the reduction
  • 225. Problem with the default value Problem : max() and min() have no identity element eg : an element e for which max(e, a) = a
  • 226. Problem with the default value Problem : max() and min() have no identity element eg : an element e for which max(e, a) = a 0 cant be, max(0, -1) is not -1… −∞ is not an integer
  • 227. Problem with the default value So what is the identity element of max() and min() ?
  • 228. Problem with the default value So what is the identity element of max() and min() ? Answer : there is no identity element for max() or min()
  • 229. Problem with the default value So what is the default value of max() and min() ?
  • 230. Problem with the default value So what is the default value of max() and min() ? Answer : there is no default value for max() and min()
  • 231. Problem with the default value So what is the returned value of the max() reduction ? // map / filter / reduce pattern on collections ....... = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) .max() ;
  • 232. Problem with the default value So what is the returned value of the max() reduction ? If it’s int, then the default value will be 0… // map / filter / reduce pattern on collections ....... = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) .max() ;
  • 233. Problem with the default value So what is the returned value of the max() reduction ? If it’s int, then the default value will be 0… It it’s Integer, then the default value will be null… // map / filter / reduce pattern on collections ....... = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) .max() ;
  • 234. Optionals Since there’s none, we need another notion // map / filter / reduce pattern on collections OptionalInt optionalMax = persons.stream() .mapToInt(Person::getAge) .filter(a -> a > 20) .max() ; « there might be no result »
  • 235. Optionals What can I do with OptionalInt ? 1st pattern : test if it holds a value OptionalInt optionalMax = ... ; int max ; if (optionalMax.isPresent()) { max = optionalMax.get() ; } else { max = ... ; // decide a « default value » }
  • 236. Optionals What can I do with OptionalInt ? 1st pattern bis : read the held value, giving a default value OptionalInt optionalMax = ... ; // get 0 if no held value int max = optionalMax.orElse(0) ;
  • 237. Optionals What can I do with OptionalInt ? 2nd pattern : read the held value, can get an exception OptionalInt optionalMax = ... ; // throws NoSuchElementException if no held value int max = optionalMax.getAsInt() ;
  • 238. Optionals What can I do with OptionalInt ? 2nd pattern bis : read the held value, or throw an exception OptionalInt optionalMax = ... ; // exceptionSupplier will supply an exception, if no held value int max = optionalMax.orElseThrow(exceptionSupplier) ;
  • 240. Available reductions On Stream<T> : - reduce(), with different parameters - count(), min(), max() - anyMatch(), allMatch(), noneMatch() - findFirst(), findAny() - toArray() - forEach(), forEachOrdered()
  • 241. Available reductions On IntStream, LongStream, DoubleStream : - average() - summaryStatistics()
  • 243. Mutable reductions : example 1 Use of the helper class : Collectors ArrayList<String> strings = stream .map(Object::toString) .collect(Collectors.toList()) ;
  • 244. Mutable reductions : example 2 Concatenating strings with a helper String names = persons .stream() .map(Person::getName) .collect(Collectors.joining()) ;
  • 245. Mutable reductions Common things : - have a container : Collection or StringBuilder - have a way to add an element to the container - have a way to merge two containers (for parallelization)
  • 246. Mutable reductions : example 1 Putting things together : ArrayList<String> strings = stream .map(Object::toString) .collect( () -> new ArrayList<String>(), // the supplier (suppliedList, s) -> suppliedList.add(s), // the accumulator (supplied1, supplied2) -> supplied1.addAll(supplied2) // the combiner ) ;
  • 247. Mutable reductions : example 1 Putting things together : ArrayList<String> strings = stream .map(Object::toString) .collect( ArrayList::new, // the supplier ArrayList::add, // the accumulator ArrayList::addAll // the combiner ) ;
  • 248. Mutable reductions : example 1 Putting things together : ArrayList<String> strings = stream .map(Object::toString) .collect( ArrayList::new, // the supplier ArrayList::add, // the accumulator ArrayList::addAll // the combiner ) ; ArrayList<String> strings = stream .map(Object::toString) .collect(Collectors.toList()) ;
  • 250. The Collectors class A rich toolbox (37 methods) for various types of reductions - counting, minBy, maxBy - summing, averaging, summarizing - joining - toList, toSet And - mapping, groupingBy, partionningBy
  • 251. The Collectors class Average, Sum, Count persons .stream() .collect(Collectors.averagingDouble(Person::getAge)) ; persons .stream() .collect(Collectors.counting()) ;
  • 252. The Collectors class Concatenating the names in a String String names = persons .stream() .map(Person::getName) .collect(Collectors.joining(", ")) ;
  • 253. The Collectors class Accumulating in a List, Set Set<Person> setOfPersons = persons .stream() .collect( Collectors.toSet()) ;
  • 254. The Collectors class Accumulating in a custom collection TreeSet<Person> treeSetOfPersons = persons .stream() .collect( Collectors.toCollection(TreeSet::new)) ;
  • 255. The Collectors class Getting the max according to a comparator Bonus : new API to build comparators Optional<Person> optionalPerson = persons .stream() .collect( Collectors.maxBy( Comparator.comparing(Person::getAge)) ;
  • 256. Building comparators New API to build comparators in a declarative way Comparator<Person> comp = Comparator.comparing(Person::getLastName) .thenComparing(Person::getFirstName) .thenComparing(Person:getAge) ;
  • 257. Other examples Interface Predicate Predicate<Long> p1 = i -> i > 20 ; Predicate<Long> p2 = i -> i < 50 ; Predicate<Long> p3 = p1.and(p2) ; Person stephan = ... ; Predicate<Person> p = Predicat.isEqual(stephan) ;
  • 258. The Collector API : groupingBy « Grouping by » builds hash maps - must explain how the keys are built - by default the values are put in a list - may specify a downstream (ie a collector)
  • 259. The Collector API : groupingBy Grouping a list of persons by their age Map<Integer, List<Person>> map = persons .stream() .collect( Collectors.groupingBy(Person::getAge)) ;
  • 260. The Collector API : groupingBy Grouping a list of persons by their age Map<Integer, Set<Person>> map = persons .stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.toSet() // the downstream ) ;
  • 261. The Collector API : groupingBy Grouping a list of persons names by their age Map<Integer, Set<String>> map = persons .stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.mapping( // Person::getLastName, // the downstream Collectors.toSet() // ) ) ;
  • 262. The Collector API : groupingBy Grouping a list of persons names by their age Map<Integer, TreeSet<String>> map = persons .stream() .collect( Collectors.groupingBy( Person::getAge, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new) ) ) ;
  • 263. The Collector API : groupingBy Grouping a list of blah blah blah TreeMap<Integer, TreeSet<String>> map = persons .stream() .collect( Collectors.groupingBy( Person::getAge, TreeMap::new, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new) ) ) ;
  • 264. The Collector API : groupingBy Example : creating an age histogram Gives the # of persons by age Map<Integer, Long> map = persons .stream() .collect( Collectors.groupingBy(Person::getAge, Collectors.counting()) ) ;
  • 265. The Collectors class : mapping The mapping helper method takes 2 parameter : - a function, that maps the elements of the stream - a collector, called a « downstream », that is applied to the mapped values
  • 266. The Collectors class : mapping Accumulating names in a set Set<String> set = persons .stream() .collect( Collectors.mapping( Person::getLastName, Collectors.toSet())) ;
  • 267. The Collectors class : mapping Mapping the stream, then accumulating in a collection TreeSet<String> set = persons .stream() .collect( Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ;
  • 268. The Collector API : partioningBy Creates a Map<Boolean, …> on a predicate - the map has 2 keys : TRUE and FALSE - may specify a downstream
  • 269. The Collector API : partioningBy Creates a Map<Boolean, …> on a predicate map.get(TRUE) returns the list people older than 20 Map<Boolean, List<Person>> map = persons .stream() .collect( Collectors.partitioningBy(p -> p.getAge() > 20) ) ;
  • 270. The Collector API : partioningBy Can further process the list of persons Map<Boolean, TreeSet<String>> map = persons .stream() .collect( Collectors.partitioningBy( p -> p.getAge() > 20, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ) ) ;
  • 271. The Collector API : partioningBy Can further process the list of persons Map<Boolean, TreeSet<String>> map = persons .stream() .collect( Collectors.partitioningBy( p -> p.getAge() > 20, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ) ) ; Partition the persons on age > 20
  • 272. The Collector API : partioningBy Can further process the list of persons Map<Boolean, TreeSet<String>> map = persons .stream() .collect( Collectors.partitioningBy( p -> p.getAge() > 20, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ) ) ; Gather their names…
  • 273. The Collector API : partioningBy Can further process the list of persons Map<Boolean, TreeSet<String>> map = persons .stream() .collect( Collectors.partitioningBy( p -> p.getAge() > 20, Collectors.mapping( Person::getLastName, Collectors.toCollection(TreeSet::new)) ) ) ) ; … in TreeSets
  • 274. The Collector API : collectingAndThen Collect data with a downstream Then apply a function called a « finisher » Useful for putting the result in a immutable collection
  • 275. The Collector API : collectingAndThen In this case « Map::entrySet » is a finisher Set<Map.Entry<Integer, List<Person>>> set = persons .stream() .collect( Collectors.collectingAndThen( Collectors.groupingBy( Person::getAge), // downstream, builds a map Map::entrySet // finisher, applied on the map ) ;
  • 277. 1st example Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ;
  • 278. 1st example Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ; A Stream of movies
  • 279. 1st example Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ; Building a map of year / # of movies
  • 280. 1st example Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ; Then getting the entry set
  • 281. 1st example Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ; Then getting the max by value
  • 282. 1st example Optional<Entry<Integer, Long>> opt = movies.stream().parallel() .collect( Collectors.collectingAndThen( Collectors.groupingBy( movie -> movie.releaseYear(), Collectors.counting() ), Map::entrySet ) ) .stream() .max(Map.Entry.comparingByValue()) ; Returns the year with the most movies released
  • 284. Conclusion Why are lambdas introduced in Java 8 ?
  • 285. Conclusion Why are lambdas introduced in Java 8 ? Because it’s in the mood !
  • 286.
  • 287. Conclusion Why are lambdas introduced in Java 8 ? Because it’s in the mood !
  • 288. Conclusion Why are lambdas introduced in Java 8 ? Because it’s in the mood ! Because it allows to write more compact code !
  • 289. Compact code is better ! An example of compact code (in C) #include "stdio.h" main() { int b=0,c=0,q=60,_=q;for(float i=-20,o,O=0,l=0,j,p;j=O*O,p=l*l, (!_--|(j+p>4)?fputc(b?q+(_/3):10,(i+=!b,p=j=O=l=0,c++,stdout)), _=q:l=2*O*l+i/20,O=j-p+o),b=c%q,c<2400;o=-2+b*.05) ; } http://www.codeproject.com/Articles/2228/Obfuscating-your-Mandelbrot-code
  • 290. Compact code is better ! An example of compact code (in C) #include "stdio.h" main() { int b=0,c=0,q=60,_=q;for(float i=-20,o,O=0,l=0,j,p;j=O*O,p=l*l, (!_--|(j+p>4)?fputc(b?q+(_/3):10,(i+=!b,p=j=O=l=0,c++,stdout)), _=q:l=2*O*l+i/20,O=j-p+o),b=c%q,c<2400;o=-2+b*.05) ; } http://www.codeproject.com/Articles/2228/Obfuscating-your-Mandelbrot-code ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++ ++ +++++++++++ +++++++++++++++++++++++++++++++++++ +++++++ ++++++++++++++++++++++++++++++++++++ +++++++ +++++++++++++++++++++++++++++++++++ ++++++++ ++++++++++++++++++++++++++++++++++ +++++++ +++++++++++++++++++++++++++++++++ +++++ +++++++++++++++++++++++++++++++++ ++++++ +++++++++++++++++++++++ + +++++ ++++++ +++++++++++++++++++++++ ++ ++++++ ++++++++++++++++++++++ + ++++++ ++++++++++++++++++++++ + ++++++ ++++++++++++++++++++ + + +++++++ ++++++ ++++++++ ++++++++++++++++++++ + + +++++++ ++++++++++++++++++++++ + ++++++ ++++++++++++++++++++++ + ++++++ +++++++++++++++++++++++ ++ ++++++ +++++++++++++++++++++++ + +++++ ++++++ +++++++++++++++++++++++++++++++++ ++++++ +++++++++++++++++++++++++++++++++ +++++ ++++++++++++++++++++++++++++++++++ +++++++ +++++++++++++++++++++++++++++++++++ ++++++++ ++++++++++++++++++++++++++++++++++++ +++++++ +++++++++++++++++++++++++++++++++++ +++++++ ++++++++++++++++++++++++++++++++++++ ++ +++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  • 291. Conclusion Why are lambdas introduced in Java 8 ? Because it’s in the mood ! Because it allows to write more compact code !
  • 292. Conclusion Why are lambdas introduced in Java 8 ? Because it brings new and efficient patterns, that enable easy and safe parallelization, - needed by modern applications - needed by API writers
  • 293. Conclusion Java 8 is coming, it’s the biggest update in 15 years
  • 294. Conclusion Java 8 is coming, it’s the biggest update in 15 years Moving to Java 8 means a lot of work for us developers ! - Self training - Changing our habits
  • 295. Conclusion Java 8 is coming, it’s the biggest update in 15 years Moving to Java 8 means a lot of work for us developers ! - Self training - Changing our habits - Convincing our bosses (sigh…)
  • 296. Conclusion Java 8 is coming, it’s the biggest update in 15 years Release date : 18th march 2014 !
  • 297. Conclusion Java 8 is coming, it’s the biggest update in 15 years « Java is a blue collar language. It’s not PhD thesis material but a language for a job » – James Gosling, 1997
  • 298. Conclusion Java 8 is coming, it’s the biggest update in 15 years « Language features are not a goal unto themselves; language features are enablers, encouraging or discouraging certain styles and idioms » – Brian Goetz, 2013
  • 299. Conclusion Java 8 is coming, it’s the biggest update in 15 years The good news is : Java is still Java !