SlideShare une entreprise Scribd logo
1  sur  310
Télécharger pour lire hors ligne
@JosePaumard
Les
sont parmi
nous
@JosePaumard
Les
sont parmi
nous
pour le meilleur !
#J8Stream @JosePaumard
Pourquoi s’intéresser aux
API Streams ?
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• De 1998 à 2014… seul outil : l’API Collection
 Common collections
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• De 1998 à 2014… seul outil : l’API Collection
 Common collections
• À partir de 2014… un foisonnement !
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Pourquoi autant d’offres ?
• Parce que le traitement de données devient central…
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Pourquoi autant d’offres ?
• Parce que le traitement de données devient central…
et complexe !
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Pourquoi autant d’offres ?
• Parce que le traitement de données devient central…
et complexe !
 Volumes de plus en plus importants
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Pourquoi autant d’offres ?
• Parce que le traitement de données devient central…
et complexe !
 Volumes de plus en plus importants
 Temps de réponse maîtrisés
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Pourquoi autant d’offres ?
• Parce que le traitement de données devient central…
et complexe !
 Volumes de plus en plus importants
 Temps de réponse maîtrisés
 Algorithmes complexes
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Le traitement de données a besoin de « primitives »
de haut niveau
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Le traitement de données a besoin de « primitives »
de haut niveau
 Qui permettent d’accéder aux données où qu’elles
soient
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Le traitement de données a besoin de « primitives »
de haut niveau
 Qui permettent d’accéder aux données où qu’elles
soient
 Qui exposent des fonctions (map / filter / reduce)
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Le traitement de données a besoin de « primitives »
de haut niveau
 Qui permettent d’accéder aux données où qu’elles
soient
 Qui exposent des fonctions (map / filter / reduce)
 Qui soient efficaces !
#J8Stream @JosePaumard
Traitement de donnéesTraitement de données
• Le traitement de données a besoin de « primitives »
de haut niveau
 Qui permettent d’accéder aux données où qu’elles
soient
 Qui exposent des fonctions (map / filter / reduce)
 Qui soient efficaces !
 Éventuellement parallèles
#J8Stream @JosePaumard
Objet de la présentationObjet de la présentation
• Présenter trois API
 Exposer les concepts fondamentaux
 Présenter les fonctions implémentées
 Montrer des patterns de code (Java 8, lambdas)
• Comparer ces API
 Point de vue de l’utilisateur
 Performances !
#J8Stream @JosePaumard
Objet de la présentationObjet de la présentation
• Proposer une grille de lecture et d’analyse
 Comparer des outils qui proposent des solutions
différentes pour un même problème
#J8Stream @JosePaumard
Objet de la présentationObjet de la présentation
• Proposer une grille de lecture et d’analyse
 Comparer des outils qui proposent des solutions
différentes pour un même problème
• Du point de vue du développeur
#J8Stream @JosePaumard
Objet de la présentationObjet de la présentation
• Proposer une grille de lecture et d’analyse
 Comparer des outils qui proposent des solutions
différentes pour un même problème
• Du point de vue du développeur
 Performance
 Patterns écriture / lecture
#J8Stream @JosePaumard
Questions ?
#J8Stream
Questions ?
#J8Stream
#J8Stream @JosePaumard
Les forces en présenceLes forces en présence
• Les 3 API sont :
 L’API Stream de Java 8
#J8Stream @JosePaumard
Les forces en présenceLes forces en présence
• Les 3 API sont :
 L’API Stream de Java 8
 GS Collections
#J8Stream @JosePaumard
Les forces en présenceLes forces en présence
• Les 3 API sont :
 L’API Stream de Java 8
 GS Collections
 RxJava
#J8Stream @JosePaumard
Les forces en présenceLes forces en présence
• Les 3 API sont :
 L’API Stream de Java 8
 GS Collections
 RxJava
• Comparaison des performances sur un exemple
commun
#J8Stream @JosePaumard
API Stream
#J8Stream @JosePaumard
API StreamAPI Stream
• Qu’est-ce qu’un Stream Java 8 ?
 Un objet que l’on connecte à une source
#J8Stream @JosePaumard
API StreamAPI Stream
• Qu’est-ce qu’un Stream Java 8 ?
 Un objet que l’on connecte à une source
 Un objet qui ne porte pas les données qu’il traite
#J8Stream @JosePaumard
API StreamAPI Stream
• Qu’est-ce qu’un Stream Java 8 ?
 Un objet que l’on connecte à une source
 Un objet qui ne porte pas les données qu’il traite
 Un objet qui expose le pattern map / filter / reduce
#J8Stream @JosePaumard
API StreamAPI Stream
• Qu’est-ce qu’un Stream Java 8 ?
 Un objet que l’on connecte à une source
 Un objet qui ne porte pas les données qu’il traite
 Un objet qui expose le pattern map / filter / reduce
• Nouveau concept introduit dans le JDK
#J8Stream @JosePaumard
API StreamAPI Stream
• Exemple
List<String> liste = Arrays.asList("un", "deux", "trois") ;
liste.stream() 
.map(s ‐> s.toUpperCase())
.max(Comparator.comparing(s ‐> s.length()))
.ifPresent(s ‐> System.out.println(s)) ;
#J8Stream @JosePaumard
API StreamAPI Stream
• Exemple
List<String> liste = Arrays.asList("un", "deux", "trois") ;
liste.stream()  // ouverture d’un stream de String
.map(s ‐> s.toUpperCase()) 
.max(Comparator.comparing(s ‐> s.length()))
.ifPresent(s ‐> System.out.println(s)) ;
#J8Stream @JosePaumard
API StreamAPI Stream
• Exemple
List<String> liste = Arrays.asList("un", "deux", "trois") ;
liste.stream()
.map(s ‐> s.toUpperCase()) // mise en majuscules des éléments
.max(Comparator.comparing(s ‐> s.length()))
.ifPresent(s ‐> System.out.println(s)) ;
#J8Stream @JosePaumard
API StreamAPI Stream
• Exemple
List<String> liste = Arrays.asList("un", "deux", "trois") ;
liste.stream()
.map(s ‐> s.toUpperCase())
.max(Comparator.comparing(s ‐> s.length())) // plus longue
.ifPresent(s ‐> System.out.println(s)) ;
#J8Stream @JosePaumard
API StreamAPI Stream
• Exemple
List<String> liste = Arrays.asList("un", "deux", "trois") ;
liste.stream()
.map(s ‐> s.toUpperCase())
.max(Comparator.comparing(s ‐> s.length()))
.ifPresent(s ‐> System.out.println(s)) ; // Optional !
#J8Stream @JosePaumard
API StreamAPI Stream
• Exemple
List<String> liste = Arrays.asList("un", "deux", "trois") ;
liste.stream()
.map(String::toUpperCase)
.max(Comparator.comparing(String::length)
.ifPresent(System.out::println) ; // Optional !
#J8Stream @JosePaumard
CollectorsCollectors
• On peut collecter des données
List<Person> liste = ... ;
liste.stream()
.filter(person ‐> person.getAge() > 30)
.collect(
Collectors.groupingBy(
Person::getAge,       // key extractor
Collectors.counting() // downstream collector
)
) ;
#J8Stream @JosePaumard
CollectorsCollectors
• On peut collecter des données
List<Person> liste = ... ;
liste.stream()
.filter(person ‐> person.getAge() > 30)
.collect(
Collectors.groupingBy(
Person::getAge,       // key extractor
Collectors.counting() // downstream collector
)
) ;
#J8Stream @JosePaumard
CollectorsCollectors
• On peut collecter des données
List<Person> liste = ... ;
Map<Integer, Long> map = 
liste.stream()
.filter(person ‐> person.getAge() > 30)
.collect(
Collectors.groupingBy(
Person::getAge,       // key extractor
Collectors.counting() // downstream collector
)
) ;
#J8Stream @JosePaumard
CollectorsCollectors
• Et on peut paralléliser les traitements
List<Person> liste = ... ;
Map<Integer, Long> map = 
liste.stream().parallel()
.filter(person ‐> person.getAge() > 30)
.collect(
Collectors.groupingBy(
Person::getAge,       // key extractor
Collectors.counting() // downstream collector
)
) ;
#J8Stream @JosePaumard
Particularisation d’un StreamParticularisation d’un Stream
• On peut le connecter à sa propre source de données
 Implémenter un Spliterator (~ Iterator)
#J8Stream @JosePaumard
Particularisation d’un StreamParticularisation d’un Stream
• On peut le connecter à sa propre source de données
 Implémenter un Spliterator (~ Iterator)
• On peut implémenter son propre Collector
#J8Stream @JosePaumard
GS Collections
#J8Stream @JosePaumard
IntroductionIntroduction
• API Open source, Github
• Développé par Goldman Sachs
• Contribution importante
https://github.com/goldmansachs/gs-collections
#J8Stream @JosePaumard
GS CollectionsGS Collections
• Une alternative à l’API Collection
 Parfois très ressemblante…
• Des interfaces supplémentaires
 Beaucoup !
 Des méthodes supplémentaires sur les interfaces
existantes
#J8Stream @JosePaumard
GS CollectionsGS Collections
• Nouveaux concepts ?
#J8Stream @JosePaumard
GS CollectionsGS Collections
• Nouveaux concepts ?
• Oui et non…
#J8Stream @JosePaumard
GS CollectionsGS Collections
• Nouveaux concepts ?
• Oui et non…
 Bag
#J8Stream @JosePaumard
GS CollectionsGS Collections
• Nouveaux concepts ?
• Oui et non…
 Bag
 MultiMap
#J8Stream @JosePaumard
GS CollectionsGS Collections
• Nouveaux concepts ?
• Oui et non…
 Bag
 MultiMap
 MutableSet
#J8Stream @JosePaumard
GS CollectionsGS Collections
• Nouveaux concepts ?
• Plutôt des extensions des concepts de
l’API Collection
#J8Stream @JosePaumard
GS CollectionsGS Collections
• Nouveaux concepts ?
• Plutôt des extensions des concepts de
l’API Collection
 Certains sont dans Common collections ou Guava
#J8Stream @JosePaumard
Structures fondamentalesStructures fondamentales
• Bag = Collection
• Existe en plusieurs couleurs !
#J8Stream @JosePaumard
Structures fondamentalesStructures fondamentales
• Bag = Collection
• Existe en plusieurs couleurs !
• Primitifs : IntBag, LongBag, …
#J8Stream @JosePaumard
Structures fondamentalesStructures fondamentales
• Bag = Collection
• Existe en plusieurs couleurs !
• Primitifs : IntBag, LongBag, …
• ImmutableBag, MutableBag
#J8Stream @JosePaumard
Structures fondamentalesStructures fondamentales
• Bag = Collection
• Existe en plusieurs couleurs !
• Primitifs : IntBag, LongBag, …
• ImmutableBag, MutableBag
• Sorted, Unsorted
#J8Stream @JosePaumard
Structures fondamentalesStructures fondamentales
• Bag = Collection
• Existe en plusieurs couleurs !
• Primitifs : IntBag, LongBag, …
• ImmutableBag, MutableBag
• Sorted, Unsorted
• Synchronized
#J8Stream @JosePaumard
Structures fondamentalesStructures fondamentales
• Bag, List, Set, Stack, Map, Multimap
#J8Stream @JosePaumard
Structures fondamentalesStructures fondamentales
• Bag, List, Set, Stack, Map, Multimap
• Nombreuses implémentations
#J8Stream @JosePaumard
BagBag
• Méthodes originales type Collection
Bag<Person> bag = ... ;
int numberOfPaul = bag.occurenceOf(paul) ;
#J8Stream @JosePaumard
BagBag
• Méthodes originales type Collection
Bag<Person> bag = ... ;
int numberOfPaul = bag.occurenceOf(paul) ;
int numberOfDistinct = bag.sizeDistinct() ;
#J8Stream @JosePaumard
BagBag
• Méthodes originales type Collection
Bag<Person> bag = ... ;
int numberOfPaul = bag.occurenceOf(paul) ;
int numberOfDistinct = bag.sizeDistinct() ;
Bag<Customer> customers = bag.instanceOf(Customer.class) ;
#J8Stream @JosePaumard
BagBag
• Méthodes originales type Collection
Bag<Person> bag = ... ;
Partition<Person> partition = 
bag.partition(person ‐> person.getAge() > 30) ;
#J8Stream @JosePaumard
BagBag
• Méthodes originales type Collection
Bag<Person> bag = ... ;
Partition<Person> partition = 
bag.partition(person ‐> person.getAge() > 30) ;
Bag<Person> selected = partition.getSelected() ;
Bag<Person> rejected = partition.getRejected() ;
#J8Stream @JosePaumard
BagBag
• Méthodes originales type Collection
Bag<Person> bag = ... ;
Partition<Person> partition = 
bag.partition(person ‐> person.getAge() > 30) ;
Bag<Person> selected = partition.getSelected() ;
Bag<Person> rejected = partition.getRejected() ;
Bag<Person> selected = bag.select(person ‐> person.getAge() > 30) ;
Bag<Person> rejected = bag.reject(person ‐> person.getAge() > 30) ;
#J8Stream @JosePaumard
BagBag
• Méthode forEach()
Bag<Person> bag = ... ;
bag.forEach(System.out::println) ;
#J8Stream @JosePaumard
BagBag
• Méthode forEach()
Bag<Person> bag = ... ;
bag.forEach(System.out::println) ; // compiler error
#J8Stream @JosePaumard
BagBag
• Méthode forEach()
Bag<Person> bag = ... ;
bag.forEach(System.out::println) ; // compiler error
public interface Iterable<T> { // java.util
default void forEach(Consumer<? super T> action) {...}
}
#J8Stream @JosePaumard
BagBag
• Méthode forEach()
Bag<Person> bag = ... ;
bag.forEach(System.out::println) ; // compiler error
public interface InternalIterable<T> { // GS Collection 
void forEach(Procedure<? super T> procedure) ;
}
#J8Stream @JosePaumard
BagBag
• Méthode forEach()
Bag<Person> bag = ... ;
bag.forEach((Procedure<String>)System.out::println) ;
#J8Stream @JosePaumard
BagBag
• Méthodes map & filter
Bag<Person> bag = ... ;
Bag<String> names = bag.collect(Person::getAge) ;      // eq. map()
Bag<String> names = bag.select(p ‐> p.getAge() > 30) ; // eq filter()
#J8Stream @JosePaumard
BagBag
• Méthodes map & filter
Bag<Person> bag = ... ;
Bag<String> names = bag.collect(Person::getAge) ;      // eq. map()
Bag<String> names = bag.select(p ‐> p.getAge() > 30) ; // eq filter()
Bag<T> tap(Procedure<? super T> procedure) ;
#J8Stream @JosePaumard
BagBag
• Méthodes map & flatMap
Bag<T> collect( // eq. map()
Function<? super T, ? extends V> function) {...}
Bag<T> flatCollect( // eq. flatMap()
Function<? super T, ? extends Iterable<V>> function) {...}
#J8Stream @JosePaumard
BagBag
• Méthodes map & filter fusionnées
Bag<Person> bag = ... ;
names = bag.collectIf(person ‐> person.getAge() > 30, 
Peson::getName) ;
#J8Stream @JosePaumard
BagBag
• Méthodes de réduction
Bag<Person> bag = ... ;
boolean b1 = bag.allSatisfy(person ‐> person.getAge() > 30) ;
boolean b2 = bag.anySatisfy(person ‐> person.getAge() > 100) ;
boolean b3 = bag.noneSatisfy(person ‐> person.getAge() < 18) ;
#J8Stream @JosePaumard
BagBag
• Méthodes de réduction
Bag<Person> bag = ... ;
Person first = bag.detect(
person ‐> person.getAge() > 30) ;
Person p = bag.detectIfNone(
person ‐> person.getAge() > 100, 
() ‐> Person.NOBODY) ;
#J8Stream @JosePaumard
BagBag
• Méthodes de réduction
Bag<Person> bag = ... ;
Person first = bag.detectWith(
(person, param) ‐> person.getAge() > param, 
30) ;
Person p = bag.detectWithIfNone(
(person, param) ‐> person.getAge() > param, 
100, 
() ‐> Person.NOBODY) ;
#J8Stream @JosePaumard
BagBag
• Méthodes de folding
Bag<Person> bag = ... ;
long sum = bag.injectInto(
0L, 
(sum, person) ‐> sum + person.getAge()) ;
long count = bag.injectInto(
0L, 
(sum, person) ‐> sum + 1L) ;
#J8Stream @JosePaumard
BagBag
• Méthodes de folding
Bag<Person> bag = ... ;
long sum = bag.injectInto(
0L, 
(l, person) ‐> l + person.getAge()) ;
long sumOfAge = bag.sumOfInt(Person::getAge)) ;
#J8Stream @JosePaumard
BagBag
• Méthodes de folding
Bag<Person> bag = ... ;
String names = bag.collect(Person::getName).makeString() ;
Charles, Michelle, Paul, Barbara
#J8Stream @JosePaumard
BagBag
• Réduction dans une chaîne de caractères
Bag<Person> bag = ... ;
String names = bag.collect(Person::getAge).makeString() ;
String names = bag.collect(Person::getAge).makeString(" ; ") ;
Charles ; Michelle ; Paul ; Barbara
#J8Stream @JosePaumard
BagBag
• Réduction dans une chaîne de caractères
Bag<Person> bag = ... ;
String names = bag.collect(Person::getAge).makeString() ;
String names = bag.collect(Person::getAge).makeString(" ; ") ;
String names = bag.collect(Person::getAge).makeString("{", " ; ", "}") ;
{Charles ; Michelle ; Paul ; Barbara}
#J8Stream @JosePaumard
BagBag
• Réduction dans une chaîne de caractères
Bag<Person> bag = ... ;
bag.collect(Person::getAge)
.appendString(StringBuilder::new) ;
#J8Stream @JosePaumard
BagBag
• Réduction dans une table de hachage
Bag<Person> bag = ... ;
MapIterable<Integer, Bag<Person>> map = 
bag.aggregateBy(
Person::getAge,       // key extractor
FastList::new,        // zero factory
(list, person) ‐> {   //
list.add(person) ; // merge operation
return list ;      //
}
) ;
#J8Stream @JosePaumard
BagBag
• Réduction dans une table de hachage
Bag<Person> bag = ... ;
MultiMap<Integer, Person> map = bag.groupBy(Person::getAge) ;
#J8Stream @JosePaumard
MutableMapMutableMap
• Méthodes de Map
V getIfAbsentPut(K key, 
Function0<? extends V> function) ;
V getIfAbsentPutWithKey(K key, 
Function<? super K, ? extends V> function) ;
V getIfAbsentPutWith(K key, 
Function<? super P, ? extends V> function
P parameter) ;
#J8Stream @JosePaumard
MutableMapMutableMap
• Méthodes forEach()
void forEachKeyValue(Procedure2<? super K, ? super V> procedure) ;
void forEachKey(Procedure<? super T> procedure) ;
void forEachValue(Procedure<? super T> procedure) ;
#J8Stream @JosePaumard
MutableMapMutableMap
• Méthodes map
• Une table de hachage est aussi une liste de valeurs
MapIterable<K2, V2> 
collect(Function2<? super K, ? super V, Pair<K2, V2>> function) ;
public interface MapIterable<K, V> extends RichIterable<V> {
}
#J8Stream @JosePaumard
PairPair
• Modélisation d’un tuple
public interface Pair<T1, T2>
extends Serializable, Comparable<Pair<T1, T2>> {
T1 getOne();
T2 getTwo();
void put(Map<T1, T2> map);
Map.Entry<T1, T2> toEntry(); // pont avec API Collection 
Pair<T2, T1> swap();
}
#J8Stream @JosePaumard
MutableMapMutableMap
• Les méthodes map, filter et méthodes de réduction
sont définies sur RichIterable
 Donc disponibles sur les tables de hachage
 Elles opèrent sur les valeurs
• Méthodes groupBy, retournent de nouvelles tables
reject(Predicate2<? super K, ? super V> predicate) ;
select(Predicate2<? super K, ? super V> predicate) ;
#J8Stream @JosePaumard
ImmutableMapImmutableMap
• Méthodes pour « ajouter » des clés / valeurs
MutableMapIterable<K, V> withKeyValue(K key, V value) ; // put
MutableMapIterable<K, V> withoutKey(K key) ; // remove
#J8Stream @JosePaumard
MultiMapMultiMap
• Concept qui ne fait pas partie de l’API Collection
• Map qui associe plusieurs valeurs à une même clé
 Gère une collection de valeurs en interne
MultiMap<Integer, Person> map ;  // GS Collections
Map<Integer, List<Person>> map ; // API Collection
#J8Stream @JosePaumard
MultiMapMultiMap
• La plupart des méthodes sont les mêmes
• Méthodes get différentes
RichIterable<V> values = multiMap.get(K key) ;
MutableMap<K, RichIterable<V>> map = multiMap.toMap() ;
#J8Stream @JosePaumard
Structures concurrentesStructures concurrentes
• ConcurrentHashMap
 Construite sur un tableau de Entry
(AtomicReferenceArray)
 Accès via des AtomicReference
 Même structure que java.util.HashMap
#J8Stream @JosePaumard
Opérations de type ZipOpérations de type Zip
• Permet d’appairer deux ensembles
Bag<Person> bag1 = ImmutableBagImpl.of(anna, charles) ;
Bag<Person> bag2 = ImmutableBagImpl.of(paul, barbara) ;
Bag<Pair<Person, Person>> friends = bag1.zip(bag2) ;
#J8Stream @JosePaumard
Opérations de type ZipOpérations de type Zip
• Permet d’appairer deux ensembles
Bag<Person> bag1 = ImmutableBagImpl.of(anna, charles) ;
Bag<Person> bag2 = ImmutableBagImpl.of(paul, barbara) ;
Bag<City> bag3 = ImmutableBagImpl.of(paris, sanFrancisco) ;
Bag<Pair<Person, Person>> friends = bag1.zip(bag2) ;
Bag<Pair<Person, City>> living = bag1.zip(bag3) ;
#J8Stream @JosePaumard
Opérations de type ZipOpérations de type Zip
• Permet d’appairer deux ensembles
Bag<Person> bag1 = ImmutableBagImpl.of(anna, charles) ;
Bag<Person> bag2 = ImmutableBagImpl.of(paul, barbara) ;
Bag<City> bag3 = ImmutableBagImpl.of(paris, sanFrancisco) ;
Bag<Pair<Person, Person>> friends = bag1.zip(bag2) ;
Bag<Pair<Person, City>> living = bag1.zip(bag3) ;
Bag<Pair<City, Integer>> cities = bag3.zipWithIndex() ;
#J8Stream @JosePaumard
Classes factoryClasses factory
• Factory pour Bag, List, Set, Stack, Map
Bag<Long> bagOfInteger = MutableBagFactoryImpl.of(1L, 2L, 5L) ;
Bag<Person> bagOfPerson = MutableBagFactoryImpl.of(persons) ;
#J8Stream @JosePaumard
ImplémentationsImplémentations
• Pas de miracle à attendre…
// class FastList
public boolean add(T newItem) {
if (this.items.length == this.size) {
this.ensureCapacityForAdd();
}
this.items[this.size++] = newItem;
return true;
}
#J8Stream @JosePaumard
ImplémentationsImplémentations
• Pas de miracle à attendre…
// class FastList
public boolean add(T newItem) {
if (this.items.length == this.size) {
this.ensureCapacityForAdd();
}
this.items[this.size++] = newItem;
return true;
}
// class ArrayList
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
#J8Stream @JosePaumard
ImplémentationsImplémentations
• Une implémentation est différente : celle des tables
de hachage
 Fonctionne avec un tableau unique
#J8Stream @JosePaumard
BizarreriesBizarreries
• Quelques bizarreries
MutableMap<K, V> map1 = map.asUnmodifiable() ; // UnmodifiableMap ?
#J8Stream @JosePaumard
Bilan sur l’APIBilan sur l’API
• Une API complète (complexe)
• Concept de MultiMap
• Des méthodes que l’on trouve sur Stream
 Ajoutées aux collections
• Des méthodes supplémentaires
 Que l’on aura peut-être sur Stream (zip)
#J8Stream @JosePaumard
RxJava
#J8Stream @JosePaumard
RxJavaRxJava
• API Open source, Github
• Développé par Netflix
• Version Java de ReactiveX
 .NET
 Python, Kotlin, JavaScript, Scala, Ruby, Groovy, Rust
 Android
https://github.com/ReactiveX/RxJava
#J8Stream @JosePaumard
Vue d’ensembleVue d’ensemble
• Approche différente de GS Collections
• Il ne s’agit pas d’une implémentation alternative de
l’API Collection
• Mais plutôt de l’implémentation du pattern Reactor
#J8Stream @JosePaumard
Pattern ReactorPattern Reactor
• Set (fixed size, mutable, immutable, primitifs)
• SortedSet (fixed size, mutable, immutable, primitifs)
• Pool
• Stack (mutable, immutable, primitifs)
http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf
#J8Stream @JosePaumard
Notions fondamentalesNotions fondamentales
• Observable : source de données
#J8Stream @JosePaumard
Notions fondamentalesNotions fondamentales
• Observable : source de données
 Objet complexe ~100 méthodes statiques + ~150
méthodes non statiques
#J8Stream @JosePaumard
Notions fondamentalesNotions fondamentales
• Observable : source de données
 Objet complexe ~100 méthodes statiques + ~150
méthodes non statiques
• Observer : permet d’observer un observable
 Objet simple : 3 méthodes
#J8Stream @JosePaumard
Notions fondamentalesNotions fondamentales
• Observable : source de données
 Objet complexe ~100 méthodes statiques + ~150
méthodes non statiques
• Observer : permet d’observer un observable
 Objet simple : 3 méthodes
• Subscription : lien qui existe entre un observable et
un observer
#J8Stream @JosePaumard
Notions fondamentalesNotions fondamentales
• Observer
public interface Observer<T> {
public void onNext(T t);
public void onCompleted();
public void onError(Throwable e);
}
#J8Stream @JosePaumard
Notions fondamentalesNotions fondamentales
• Associer un observer à un observable
Observable<T> observable = ... ;
Subscription subscription = observable.subscribe(observer) ;
public interface Subscription {
public void unsubscribe();
public void isUnsubscribe();
}
#J8Stream @JosePaumard
Création d’un ObservableCréation d’un Observable
• Constructeur non vide protégé
#J8Stream @JosePaumard
Création d’un ObservableCréation d’un Observable
• Constructeur non vide protégé
• On peut construire un Observable
 par extension
 en utilisant une des méthodes statiques
#J8Stream @JosePaumard
Création d’un ObservableCréation d’un Observable
• Constructeur non vide protégé
• On peut construire un Observable
 par extension
 en utilisant une des méthodes statiques
• Prend un producer en paramètre
#J8Stream @JosePaumard
Création d’un ObservableCréation d’un Observable
• Création à partir de collections
Observable<String> obs1 = Observable.just("one",  "two", "three") ;
List<String> strings = Arrays.asList("one",  "two", "three") ;
Observable<String> obs2 = Observable.from(strings) ;
#J8Stream @JosePaumard
Création d’un ObservableCréation d’un Observable
• Création à partir de collections
Observable<String> obs1 = Observable.just("one",  "two", "three") ;
List<String> strings = Arrays.asList("one",  "two", "three") ;
Observable<String> obs2 = Observable.from(strings) ;
Observable<String> empty = Observable.empty() ;
Observable<String> never = Observable.never() ;
Observable<String> error = Observable.<String>error(exception) ;
#J8Stream @JosePaumard
Création d’un ObservableCréation d’un Observable
• Création de séries
Observable<Long> longs = Observable.range(1L, 100L) ;
#J8Stream @JosePaumard
Création d’un ObservableCréation d’un Observable
• Création de séries
Observable<Long> longs = Observable.range(1L, 100L) ;
// interval
Observable<Long> timeSerie1 = 
Observable.interval(1L, TimeUnit.MILLISECONDS) ; // a serie of longs
// initial delay, then interval
Observable<Long> timeSerie2 = 
Observable.timer(10L, 1L, TimeUnit.MILLISECONDS) ; // one 0
#J8Stream @JosePaumard
Création d’un ObservableCréation d’un Observable
• Méthode using()
public final static <T, Resource> Observable<T> using(
final Func0<Resource> resourceFactory, // producer
final Func1<Resource, Observable<T>> observableFactory, // function
final Action1<? super Resource> disposeAction // consumer
) { }
#J8Stream @JosePaumard
Notion de SchedulerNotion de Scheduler
• Ces méthodes peuvent prendre un autre paramètre
• Scheduler : interface
• Associée à la factory Schedulers
Observable<Long> longs = Observable.range(0L, 100L, scheduler) ;
#J8Stream @JosePaumard
Notion de SchedulerNotion de Scheduler
• Factory Schedulers
public final class Schedulers {
public static Scheduler immediate() {...}   // immediate, same thread
public static Scheduler newThread() {...}   // new thread
public static Scheduler computation() {...} // computation ES
public static Scheduler io() {...}          // IO growing ES
}
#J8Stream @JosePaumard
Notion de SchedulerNotion de Scheduler
• Factory Schedulers
public final class Schedulers {
public static Scheduler trampoline() {...} // queued in the current
// thread
public static Scheduler test() {...}
public static Scheduler fromExecutor(Executor executor) {...}
}
#J8Stream @JosePaumard
Notion de SchedulerNotion de Scheduler
• RxJava permet de créer des Observable dans
différents threads
• Certains pools sont spécialisés : IO, Computation
• On peut passer ses propres pools
• Les observateurs sont appelés dans les threads des
observables
#J8Stream @JosePaumard
Notion de SchedulerNotion de Scheduler
• La classe Scheduler n’est pas immédiate à étendre
• On utilise from() pour les threads IHM (Swing,
JavaFX)
@JosePaumard
Pause café ?
#J8Stream
@JosePaumard
Pause café !
#J8Stream
Encore du RxJava
Patterns
Extensions de Stream
Performance
@JosePaumard
Les
sont parmi
nous
#J8Stream @JosePaumard
Observable : méthodes statiquesObservable : méthodes statiques
• Série de méthodes statiques de combinaisons
d’Observable en un seul
#J8Stream @JosePaumard
Observable de listesObservable de listes
• amb() : prend une liste d’Observable et suit le premier
qui parle
©RxJava
O1
O2
O1
#J8Stream @JosePaumard
Observable de listesObservable de listes
• combineLatest() : applique une fonction aux deux
derniers éléments émis
©RxJava
O1
O2
F(O1, O2)
#J8Stream @JosePaumard
Observable de listesObservable de listes
• zip() : équivalent d’un combine, mais prend les
éléments un par un
©RxJava
O1
O2
F(O1, O2)
#J8Stream @JosePaumard
Observable de listesObservable de listes
• concat() : émet O1 puis O2, sans les mélanger
• merge() : émet O1 et O2, s’arrête sur erreur
#J8Stream @JosePaumard
Observable de listesObservable de listes
• concat() : émet O1 puis O2, sans les mélanger
• merge() : émet O1 et O2, s’arrête sur erreur
©RxJava©RxJava
#J8Stream @JosePaumard
Observable de listesObservable de listes
• concat() : émet O1 puis O2, sans les mélanger
• merge() : émet O1 et O2, s’arrête avec le premier
• mergeDelayError() : reporte l’erreur à la fin
©RxJava
#J8Stream @JosePaumard
Observable de listesObservable de listes
• sequenceEqual() : compare deux séquences
©RxJava
O1
O2
boolean
#J8Stream @JosePaumard
Observable d’ObservableObservable d’Observable
• switchOnNext() : un peu spécial…
#J8Stream @JosePaumard
Observable d’ObservableObservable d’Observable
• Paramètres des méthodes précédentes :
public final static <T> Observable<T> merge(
Iterable<Observable<T>> listOfSequences) { }
#J8Stream @JosePaumard
Observable d’ObservableObservable d’Observable
• Paramètres des méthodes précédentes :
public final static <T> Observable<T> merge(
Iterable<Observable<T>> listOfSequences) { }
public final static <T> Observable<T> merge(
Observable<Observable<T>> sequenceOfSequences) { }
#J8Stream @JosePaumard
Observable d’ObservableObservable d’Observable
• Paramètres des méthodes précédentes :
public final static <T> Observable<T> merge(
Iterable<Observable<T>> listOfSequences) { }
©RxJava
#J8Stream @JosePaumard
Observable d’ObservableObservable d’Observable
• Paramètres des méthodes précédentes :
public final static <T> Observable<T> merge(
Observable<Observable<T>> sequenceOfSequences) { }
©RxJava
#J8Stream @JosePaumard
Observable d’ObservableObservable d’Observable
• switchOnNext() : prend le nouvel Observable
©RxJava
public final static <T> Observable<T> switchOnNext(
Observable<Observable<T>> sequenceOfSequences) { }
#J8Stream @JosePaumard
ExemplesExemples
• Un petit cas simple
Observable<Integer> range1To100 = Observable.range(1L, 100L) ;
manyStrings.subscribe(System.out::println) ;
#J8Stream @JosePaumard
ExemplesExemples
• Un petit cas simple
Observable<Integer> range1To100 = Observable.range(1L, 100L) ;
manyStrings.subscribe(System.out::println) ;
> 1 2 3 4 ... 100
#J8Stream @JosePaumard
ExemplesExemples
• Un petit cas un peu plus dur
Observable<Integer> timer = Observable.timer(1, TimeUnit.SECONDS) ;
timer.subscribe(System.out::println) ;
#J8Stream @JosePaumard
ExemplesExemples
• Un petit cas un peu plus dur
• N’affiche rien…
Observable<Integer> timer = Observable.timer(1, TimeUnit.SECONDS) ;
timer.subscribe(System.out::println) ;
>
#J8Stream @JosePaumard
ExemplesExemples
• Un petit cas un peu plus dur
Observable<Integer> timer = Observable.timer(1, TimeUnit.SECONDS) ;
timer.subscribe(() ‐> {
System.out.println(Thread.currentThread().getName() + " " + 
Thread.currentThread().isDaemon()) ;
}) ;
Thread.sleep(2) ;
#J8Stream @JosePaumard
ExemplesExemples
• Un petit cas un peu plus dur
Observable<Integer> timer = Observable.timer(1, TimeUnit.SECONDS) ;
timer.subscribe(() ‐> {
System.out.println(Thread.currentThread().getName() + " " + 
Thread.currentThread().isDaemon()) ;
}) ;
Thread.sleep(2) ;
> RxComputationThreadPool‐1 ‐ true
#J8Stream @JosePaumard
ExemplesExemples
• Encore un peu plus dur
Observable<Integer> range1To100 = Observable.range(1, 100) ;
Observable<String> manyStrings = 
Observable.combineLatest(
range1To100, Observable.just("one"),
(integer, string) ‐> string) ;
#J8Stream @JosePaumard
ExemplesExemples
• Encore un peu plus dur
Observable<Integer> range1To100 = Observable.range(1, 100) ;
Observable<String> manyStrings = 
Observable.combineLatest(
range1To100, Observable.just("one"),
(integer, string) ‐> string) ;
> one (et c’est tout)
Combines two source Observables 
by emitting an item that aggregates
the latest values of each of the 
source Observables 
each time an item is received from 
either of the source Observables, 
where this aggregation is defined by 
a specified function. 
#J8Stream @JosePaumard
ExemplesExemples
• Encore un peu plus dur
Observable<Integer> serie = Observable.interval(3, TimeUnit.MILLISECONDS) ;
Observable<String> manyStrings = 
Observable.combineLatest(
serie, Observable.just("one"),
(integer, string) ‐> string) ;
#J8Stream @JosePaumard
ExemplesExemples
• Encore un peu plus dur
Observable<Integer> serie = Observable.interval(3, TimeUnit.MILLISECONDS) ;
Observable<String> manyStrings = 
Observable.combineLatest(
serie, Observable.just("one"),
(integer, string) ‐> string) ;
> one one one one one one ...
#J8Stream @JosePaumard
Observables hot & coldObservables hot & cold
• Deux mécanismes d’Observable :
 Ceux qui émettent des données lorsqu’elles sont
consommées = cold observables
 Ceux qui émettent des données, qu’elles soient
consommées ou pas = hot observables
• Un hot observable peut générer ses données
indépendamment de ses observateurs
#J8Stream @JosePaumard
Méthodes d’instance
#J8Stream @JosePaumard
Opérations callbackOpérations callback
• Retournent un Observable<T>
• ~10 versions doOn*
doOnNext(Action1<T> onNext) { } // consumer
#J8Stream @JosePaumard
Opérations booléennesOpérations booléennes
• Retournent un Observable<Boolean>
• Retournent un Observable<T> vide ou singleton
exists(Func1<T, Boolean> predicate) { }
elementAt(int index) { }
ignoreElement() { }                     // returns an empty Observable
single() { }                            // completes on error or transmits
single(Func1<T, Boolean> predicate) { } // returns the item or error
#J8Stream @JosePaumard
Opérations de mappingOpérations de mapping
• Retournent un Observable<R>
map(Func1<T, R> mapping) { } 
cast(Class<R> clazz) { } // casts the elements
timestamp() { }  // wraps the elements in a timestamped object
zipWith(Observable<U> other, 
Func2<T, U, R> zipFunction) { } // BiFunction
flatMap(Func1<T, Observable<R>> mapping) { }
#J8Stream @JosePaumard
Opérations de filtrageOpérations de filtrage
• Retourne un Observable<T>
filter(Func1<T, Boolean> predicate) { } 
#J8Stream @JosePaumard
Opérations de sélectionOpérations de sélection
• Retournent un Observable<R>
sample(long period, TimeUnit timeUnit) { }
©RxJava
O1
sampler
#J8Stream @JosePaumard
Opérations de sélectionOpérations de sélection
• Retournent un Observable<R>
sample(Observable<U> sampler) { } // samples on emission & completion
©RxJava
O1
sampler
#J8Stream @JosePaumard
Remarque sur le tempsRemarque sur le temps
• RxJava peut mesurer le temps « en réel »
• Peut aussi utiliser un Observable comme mesure du
temps
 Appels à onNext() et onComplete()
#J8Stream @JosePaumard
Sélection d’élémentsSélection d’éléments
• Retournent Observable<T>
• Exception en cas de timeout entre deux émissions
first() { }
last() { }
skip(int n) { }
limit(int n) { }
take(int n) { }
timeout(long n, TimeUnit timeUnit) { }
timeout(Func0<Observable<U>> firstTimeoutSelector,   // producer
Func1<T, Observable<V>> timeoutSelector) { } // function
#J8Stream @JosePaumard
Méthodes de réductionMéthodes de réduction
• Retourne un Observable<> singleton
• Retourne un Observable<T>
all(Func1<T, Boolean> predicate) { }   // Observable<Boolean>
count() { }  // Observable<Long>
reduce(Func2<T, T, T> accumulator) { } // Observable<T>
scan(Func2<T, T, T> accumulator) { } // Observable<T>
forEach(Action1<T> consumer) { }  // void
#J8Stream @JosePaumard
Méthodes de collectionMéthodes de collection
• Méthode collect
collect(Func0<R> stateFactory, // producer
Action2<R, T> collector) { } // BiConsumer
#J8Stream @JosePaumard
Méthodes de collectionMéthodes de collection
• Méthode collect
• Construit une Map<T, List<String>>
collect(Func0<R> stateFactory, // producer
Action2<R, T> collector) { } // BiConsumer
collect(() ‐> new ArrayList<String>(), // producer
ArrayList::add) { } // BiConsumer
#J8Stream @JosePaumard
Méthodes de collectionMéthodes de collection
• Retournent des Observable<> singleton
toList() { }       // Observable<List<T>>
toSortedList() { } // Observable<List<T>>
toMultimap(Func1<T, K> keySelector,       // Observable<
Func1<T, V> valueSelector) { } //    Map<K, Collection<T>>
toMap(Func1<T, K> keySelector) { } // Observable<Map<K, T>>
#J8Stream @JosePaumard
Opérations join / groupJoinOpérations join / groupJoin
• Retourne un Observable<GroupedObservable<K, T>>
• GroupedObservable : observable avec une clé
groupBy(Func1<T, K> keySelector) { } // function
#J8Stream @JosePaumard
Opérations join / groupJoinOpérations join / groupJoin
• Combine deux observables, sur un timer
public final <T2, D1, D2, R> Observable<R> 
groupJoin(
Observable<T2> right, 
Func1<T, Observable<D1>> leftDuration, // function
Func1<T2, Observable<D2>> rightDuration, // function
Func2<T, Observable<T2>, R> resultSelector // bifunction
) { }
#J8Stream @JosePaumard
Opérations join / groupJoinOpérations join / groupJoin
• Les fenêtres de temps sont définies par des
observables
 Elles démarrent lorsque l’observable démarre
 Et se ferment lorsque l’observable émet un objet ou
s’arrête
#J8Stream @JosePaumard
Opérations join / groupJoinOpérations join / groupJoin
• Combine deux observables
#J8Stream @JosePaumard
Méthodes de debugMéthodes de debug
• Deux méthodes, font du mapping
• Notification : objet qui englobe des meta-données en
plus
materialize() { } // Observable<Notification<T>>
#J8Stream @JosePaumard
Méthodes de debugMéthodes de debug
• Deux méthodes, font du mapping
• Notification : objet qui englobe des métadonnées en
plus des objets de l’Observable
materialize() { } // Observable<Notification<T>>
dematerialize() { } // Observable<T>
#J8Stream @JosePaumard
Méthodes synchronesMéthodes synchrones
• Associent des opérations avec une horloge
delay(long delay, TimeUnit timeUnit) ; // Observable<T>
#J8Stream @JosePaumard
Méthodes synchronesMéthodes synchrones
• Associent des opérations avec une horloge
• Ou avec un autre Observable
delay(long delay, TimeUnit timeUnit) ; // Observable<T>
delay(Func1<T, Observable<U> func1) ; // Observable<T>
#J8Stream @JosePaumard
Méthodes synchronesMéthodes synchrones
• Limite le nombre d’éléments émis
debounce(long delay, TimeUnit timeUnit) ; // Observable<T>
©RxJava
#J8Stream @JosePaumard
Méthodes synchronesMéthodes synchrones
• Limite le nombre d’éléments émis
• Peut aussi se caler sur les événements d’un
Observable
debounce(long delay, TimeUnit timeUnit) ; // Observable<T>
debounce(Func1<T, Observable<U> func1) ;  // Observable<T>
#J8Stream @JosePaumard
Méthodes synchronesMéthodes synchrones
• Mesure du temps entre événements
• TimeInterval : wrapper pour la durée en ms et la
valeur émise
timeInterval() { } // Observable<TimeInterval<T>>
#J8Stream @JosePaumard
Méthodes synchronesMéthodes synchrones
• Méthodes throttle()
throttleFirst(long windowDuration, TimeUnit unit) { } // Observable<T>
throttleLast(long windowDuration, TimeUnit unit) { }
throttleWithTimeout(long windowDuration, TimeUnit unit) { }
#J8Stream @JosePaumard
Backpressure
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Problème : une source peut générer « trop »
d’éléments
 Par rapport à la vitesse des consommateurs
• Certaines méthodes permettent de « sauter » des
éléments
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Problème : une source peut émettre « trop »
d’éléments
 Par rapport à la vitesse des consommateurs
• Ne peut pas arriver avec les cold observables
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Problème : une source peut émettre « trop »
d’éléments
 Par rapport à la vitesse des consommateurs
• Ne peut pas arriver avec les cold observables
• Un observable cold peut devenir hot…
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Certaines méthodes permettent de « sauter » des
éléments
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Certaines méthodes permettent de « sauter » des
éléments
• Backpressure : consiste à ralentir le rythme
d’émission
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Méthodes utiles : sample() et debounce()
• Méthode buffer() : stocke les éléments avant de les
émettre
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Méthodes buffer()
buffer(int size) { }                     // Observable<List<T>>
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Méthodes buffer()
buffer(int size) { }                     // Observable<List<T>>
buffer(long timeSpan, TimeUnit unit) { } // Observable<List<T>>
buffer(long timeSpan, TimeUnit unit, int maxSize) { }
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Méthodes buffer()
buffer(int size) { }                     // Observable<List<T>>
buffer(long timeSpan, TimeUnit unit) { } // Observable<List<T>>
buffer(long timeSpan, TimeUnit unit, int maxSize) { }
buffer(Observable<O> bufferOpenings,               // Openings events
Func1<O, Observable<C>> bufferClosings) { } // Closings events
#J8Stream @JosePaumard
Méthodes backpressureMéthodes backpressure
• Méthodes window()
window(int size) { }                     // Observable<Observable<T>>
window(long timeSpan, TimeUnit unit) { } // Observable<Observable<T>>
window(long timeSpan, TimeUnit unit, int maxSize) { }
window(Observable<O> bufferOpenings,               // Openings events
Func1<O, Observable<C>> bufferClosings) { } // Closings events
#J8Stream @JosePaumard
Méthodes repeat & retryMéthodes repeat & retry
• repeat() : répète l’émission d’objets indéfiniment
repeat() { }            // Observable<T>
repeat(long times) { } // Observable<T>
#J8Stream @JosePaumard
Méthodes repeat & retryMéthodes repeat & retry
• repeat() : répète l’émission d’objets indéfiniment
• Quand l’observable appelle onComplete(), le
notification handler est invoqué
repeat() { }            // Observable<T>
repeat(long times) { } // Observable<T>
repeatWhen(
Func1<Observable<Void>>, Observable<?>> notificationHandler
) { }
#J8Stream @JosePaumard
Méthodes repeat & retryMéthodes repeat & retry
• repeat() : répète l’émission d’objets indéfiniment
• Sur cet Observable, le notification handler peut alors
invoquer :
 onComplete() ou onError(), ce qui déclenche le même
appel sur l’Observable source
 onNext(), ce qui déclenche la répétition
#J8Stream @JosePaumard
Méthodes repeat & retryMéthodes repeat & retry
• retry() : répète l’émission d’objets sur erreur
retry() { }            // Observable<T>
retry(long times) { } // Observable<T>
#J8Stream @JosePaumard
Méthodes repeat & retryMéthodes repeat & retry
• retry() : répète l’émission d’objets sur erreur
• Quand l’observable appelle onError(), le notification
handler est invoqué avec l’exception
retry() { }            // Observable<T>
retry(long times) { } // Observable<T>
retryWhen(
Func1<Observable<Throwable>>, Observable<?>> notificationHandler
) { }
#J8Stream @JosePaumard
Méthodes repeat & retryMéthodes repeat & retry
• Sur cet Observable, le notification handler peut alors
invoquer :
 onComplete() ou onError(), ce qui déclenche le même
appel sur l’Observable source
 onNext(), ce qui déclenche la répétition
#J8Stream @JosePaumard
Plusieurs ObserverPlusieurs Observer
• À la différence des Stream de Java 8, un Observable
peut avoir plusieurs observateurs
#J8Stream @JosePaumard
Plusieurs ObserverPlusieurs Observer
• À la différence des Stream de Java 8, un Observable
peut avoir plusieurs observateurs
• Ce qui peut poser des problèmes…
#J8Stream @JosePaumard
Plusieurs ObserverPlusieurs Observer
• Cas d’un cold Observable :
 La consommation par plusieurs observateurs ne pose
pas de problème
• Cas d’un hot Observable :
 Un deuxième observateur peut « manquer » les
premières valeurs
#J8Stream @JosePaumard
Plusieurs ObserverPlusieurs Observer
• Méthode cache()
• Permet de ne pas « manquer » les premières valeurs
cache() { }
cache(int capacity) { }
#J8Stream @JosePaumard
Plusieurs ObserverPlusieurs Observer
• Notion de ConnectableObserver
Observable<T> observable = ... ;
ConnectableObservable<T> connectable = observable.publish() ;
#J8Stream @JosePaumard
Plusieurs ObserverPlusieurs Observer
• Notion de ConnectableObserver
• L’enregistrement d’observateurs ne déclenche pas la
production des éléments
Observable<T> observable = ... ;
ConnectableObservable<T> connectable = observable.publish() ;
#J8Stream @JosePaumard
Plusieurs ObserverPlusieurs Observer
• Notion de ConnectableObserver
• L’enregistrement d’observateurs ne déclenche pas la
production des éléments
• Pour cela : appeler connect()
Observable<T> observable = ... ;
ConnectableObservable<T> connectable = observable.publish() ;
connectable.publish() ;
#J8Stream @JosePaumard
Bilan sur RxJavaBilan sur RxJava
• API Complète (complexe)
• Permet de gérer le lancement de traitements dans
différents pools de threads
#J8Stream @JosePaumard
Bilan sur RxJavaBilan sur RxJava
• API Complète (complexe)
• Permet de gérer le lancement de traitements dans
différents pools de threads
• Permet de synchroniser les opérations
 Sur une horloge
 Sur des références applicatives
#J8Stream @JosePaumard
Ponts entre
Java 8 Stream /
GS Collections / RxJava
#J8Stream @JosePaumard
Le meilleur des deux mondes ?Le meilleur des deux mondes ?
• Connecter GS Collections et Java 8 Stream ?
= connecter Stream et Iterable
#J8Stream @JosePaumard
Le meilleur des deux mondes ?Le meilleur des deux mondes ?
• Connecter GS Collections et Java 8 Stream ?
= connecter Stream et Iterable
• Connecter Java 8 Stream et RxJava ?
= connecter Stream et Observable
#J8Stream @JosePaumard
Spliterator et IteratorSpliterator et Iterator
• Les collections sont construites sur des Iterator
• Les Stream sont construits sur des Spliterator
Iterator<T> iterator = ... ;
Spliterator<T> spliterator = 
Spliterators.spliteratorUnknownSize(iterator, 0) ;
Spliterator<T> spliterator = 
Spliterators.spliterator(iterator, size, 0) ;
#J8Stream @JosePaumard
Spliterator et IteratorSpliterator et Iterator
• Les collections sont construites sur des Iterator
• Les Stream sont construits sur des Spliterator
Spliterator<T> spliterator = ... ;
Iterator<T> iterator = Spliterators.iterator(spliterator) ;
Iterator<T> iterator = ... ;
Iterable<T> iterable = () ‐> iterator ;
#J8Stream @JosePaumard
GS Collections & StreamGS Collections & Stream
• Le problème consiste à passer d’une Collection à un
Stream (et réciproquement)
#J8Stream @JosePaumard
GS Collections & StreamGS Collections & Stream
• Le problème consiste à passer d’une Collection à un
Stream (et réciproquement)
• Donc d’un Iterator à un Spliterator (et
réciproquement)
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Si l’on a un Iterator : facile !
Iterator<T> iterator = ... ;
Observable<T> observable = Observable.from(() ‐> iterator) ;
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Si l’on a un Iterator : facile !
• Si l’on a un Spliterator : facile !
Iterator<T> iterator = ... ;
Observable<T> observable = Observable.from(() ‐> iterator) ;
Spliterator<T> spliterator = ... ;
Observable<T> observable = 
Observable.from(() ‐> Spliterators.iterator(spliterator)) ;
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Donc si l’on a un Stream, on peut facilement
construire un Observable
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Donc si l’on a un Stream, on peut facilement
construire un Observable
• L’inverse ?
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Donc si l’on a un Stream, on peut facilement
construire un Observable
• L’inverse ?
 On peut construire un Iterator sur un Observable
 Puis un Spliterator sur un Iterator
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Implémenter un Iterator :
 Deux méthodes next() et hasNext()
 La méthode remove() et une méthode par défaut
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Un Iterator « tire » les données d’une source
• Alors qu’un Observable « pousse » les données vers
des callbacks
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Un Iterator « tire » les données d’une source
• Alors qu’un Observable « pousse » les données vers
des callbacks
• Il nous faut donc une adaptation entre les deux
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• On peut s’inspirer du JDK
public static<T> Iterator<T> 
iterator(Spliterator<? extends T> spliterator) {
class Adapter implements Iterator<T>, Consumer<T> {
// implementation
}
return new Adapter() ;
}
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• On peut s’inspirer du JDK
class Adapter implements Iterator<T>, Consumer<T> {
boolean valueReady = false ;
T nextElement;
public void accept(T t) {
valueReady = true ;
nextElement = t ;
}
public boolean hasNext() {
if (!valueReady)
spliterator.tryAdvance(this) ; // calls accept()
return valueReady ;
}
public T next() {
if (!valueReady && !hasNext())
throw new NoSuchElementException() ;
else {
valueReady = false ;
return nextElement ;
}
}
}
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• On peut s’inspirer du JDK
public static<T> Iterator<T> 
of(Observable<? extends T> obsevable) {
class Adapter implements Iterator<T> {
// implementation
}
return new Adapter() ;
}
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• On peut s’inspirer du JDK
class Adapter implements Iterator<T>, Consumer<T> {
boolean valueReady = false ;
T nextElement;
public void accept(T t) {
valueReady = true ;
nextElement = t ;
}
public boolean hasNext() {
return valueReady ;
}
public T next() {
if (!valueReady && !hasNext())
throw new NoSuchElementException() ;
else {
valueReady = false ;
return nextElement ;
}
}
}
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• On peut s’inspirer du JDKclass Adapter implements Iterator<T>, Consumer<T> {
boolean valueReady = false ;
T nextElement;
public void accept(T t) {
observable.subscribe(
element ‐> nextElement = element, // onNext
exception ‐> valueReady = false,    // onError
() ‐> valueReady = false            // onComplete
) ;
}
// next
// hasNext
}
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• On peut s’inspirer du JDKclass Adapter implements Iterator<T>, Consumer<T> {
AtomicBoolean valueReady = new AtomicBoolean(false) ;
AtomicReference<T> nextElement = new AtomicReference() ;
public void accept(T t) {
observable.subscribe(
element ‐> nextElement.set(element), // onNext
exception ‐> valueReady.set(false),    // onError
() ‐> valueReady.set(false) // onComplete
) ;
}
// next
// hasNext
}
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Peut mieux faire ?
interface Wrapper<E> {
E get() ;
}
Wrapper<Boolean> wb = () ‐> true ;
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Peut mieux faire ?
interface Wrapper<E> {
E get() ;
}
Wrapper<Boolean> wb = () ‐> true ;
Action1<Boolean> onNext = b ‐> wb.set(b) ; // should return Wrapper<T>
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Peut mieux faire ?
interface Wrapper<E> {
E get() ;
public default Wrapper<E> set(E e) {
// should return e
}
}
Wrapper<Boolean> wb = () ‐> true ;
Action1<Boolean> onNext = b ‐> wb.set(b) ; // should return Wrapper<T>
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• Peut mieux faire ?
interface Wrapper<E> {
E get() ;
public default Wrapper<E> set(E e) {
return () ‐> e ;
}
}
Wrapper<Boolean> wb = () ‐> true ;
Action1<Boolean> onNext = b ‐> wb.set(b) ; // should return Wrapper<T>
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• On peut s’inspirer du JDKclass Adapter implements Iterator<T>, Consumer<T> {
Wrapper<Boolean> valueReady = () ‐> false ;
Wrapper<T> nextElement ;
public void accept(T t) {
observable.subscribe(
element ‐> nextElement.set(element), // onNext
exception ‐> valueReady.set(false),    // onError
() ‐> valueReady.set(false) // onComplete
) ;
}
// next
// hasNext
}
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• On peut construire un Iterator sur un Observable
 Et donc un Spliterator sur un Observable
#J8Stream @JosePaumard
RxJava & StreamRxJava & Stream
• On peut construire un Iterator sur un Observable
 Et donc un Spliterator sur un Observable
• Fonctionne sur les cold Observable
#J8Stream @JosePaumard
Spliterators avancésSpliterators avancés
• Peut-on construire des Stream à la façon des
Observable ?
• Partant d’un Stream [1, 2, 3, 4, 5, …]
#J8Stream @JosePaumard
Spliterators avancésSpliterators avancés
• Peut-on construire des Stream à la façon des
Observable ?
• Partant d’un Stream [1, 2, 3, 4, 5, …]
 [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] ?
#J8Stream @JosePaumard
Spliterators avancésSpliterators avancés
• Peut-on construire des Stream à la façon des
Observable ?
• Partant d’un Stream [1, 2, 3, 4, 5, …]
 [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] ?
 [[1, 2, 3], [2, 3, 4], [3, 4, 5], …] ?
#J8Stream @JosePaumard
Spliterators avancésSpliterators avancés
• Peut-on construire des Stream à la façon des
Observable ?
• Deux Stream [10, 11, 12, …] et [50, 51, 52, …]
#J8Stream @JosePaumard
Spliterators avancésSpliterators avancés
• Peut-on construire des Stream à la façon des
Observable ?
• Deux Stream [10, 11, 12, …] et [50, 51, 52, …]
 [10, 50, 11, 51, 12, 52, …] ?
#J8Stream @JosePaumard
Spliterators avancésSpliterators avancés
• Peut-on construire des Stream à la façon des
Observable ?
• Deux Stream [10, 11, 12, …] et [50, 51, 52, …]
 [10, 50, 11, 51, 12, 52, …] ?
 [Pair(10, 50), Pair(11, 51), Pair(12, 52), …] ?
#J8Stream @JosePaumard
Spliterators avancésSpliterators avancés
• Trois méthodes pour un Spliterator
 tryAdvance(Consumer)
 trySplit(), retourne un sous-spliterator
 estimateSize()
#J8Stream @JosePaumard
GroupingSpliteratorGroupingSpliterator
• [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …]
public class GroupingSpliterator<E> implements Spliterator<Stream<E>> {
private final long grouping ;
private final Spliterator<E> spliterator ;
// implementation
}
#J8Stream @JosePaumard
GroupingSpliteratorGroupingSpliterator
• [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …]
public boolean tryAdvance(Consumer<? super Stream<E>> action) {
boolean finished = false ;
Stream.Builder<E> builder = Stream.builder() ;
for (int i = 0 ; i < grouping ; i++) {
if (!spliterator.tryAdvance(element ‐> { builder.add(element) ; })) {
finished = true ;
}
}
Stream<E> subStream = subBuilder.build() ;
action.accept(subStream) ;
return !finished ;
}
#J8Stream @JosePaumard
GroupingSpliteratorGroupingSpliterator
• [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …]
public Spliterator<Stream<E>> trySplit() {
Spliterator<E> spliterator = this.spliterator.trySplit() ;
return new GroupingSpliterator<E>(spliterator, grouping) ;
}
#J8Stream @JosePaumard
GroupingSpliteratorGroupingSpliterator
• [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …]
public long estimateSize() {
return spliterator.estimateSize() / grouping ;
}
#J8Stream @JosePaumard
RollingSpliteratorRollingSpliterator
• [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [2, 3, 4], [3, 4, 5], …]
#J8Stream @JosePaumard
RollingSpliteratorRollingSpliterator
• [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …]
public class RollingSpliterator<E> implements Spliterator<Stream<E>> {
private final int grouping ;
private final Spliterator<E> spliterator ;
private Object [] buffer ; // we cant create arrays of E
private AtomicInteger bufferWriteIndex = new AtomicInteger(0) ;
private AtomicInteger bufferReadIndex = new AtomicInteger(0) ;
// implementation
}
#J8Stream @JosePaumard
RollingSpliteratorRollingSpliterator
• [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …]
public boolean tryAdvance(Consumer<? super Stream<E>> action) {
boolean finished = false ;
if (bufferWriteIndex.get() == bufferReadIndex.get()) {
for (int i = 0 ; i < grouping ; i++) {
if (!advanceSpliterator()) {
finished = true ;
}
}
}
if (!advanceSpliterator()) {
finished = true ;
}
Stream<E> subStream = buildSubstream() ;
action.accept(subStream) ;
return !finished ;
}
#J8Stream @JosePaumard
RollingSpliteratorRollingSpliterator
• [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …]
private boolean advanceSpliterator() {
return spliterator.tryAdvance(
element ‐> { 
buffer[bufferWriteIndex.get() % buffer.length] = element ; 
bufferWriteIndex.incrementAndGet() ;
});
}
#J8Stream @JosePaumard
RollingSpliteratorRollingSpliterator
• [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …]
public Spliterator<Stream<E>> trySplit() {
return new RollingSpliterator<E>(spliterator.trySplit(), grouping) ;
}
public long estimateSize() {
return spliterator.estimateSize() ‐ grouping ;
}
#J8Stream @JosePaumard
ZippingSpliteratorZippingSpliterator
• [1, 2, 3, …], [a, b, c, …] -> [F(1, a), F(2, b), F(3, c), …]
public class ZippingSpliterator<E1, E2, R> implements Spliterator<R> {
private final Spliterator<E1> spliterator1 ;
private final Spliterator<E2> spliterator2 ;
private final BiFunction<E1, E2, R> tranform ;
// implementation
}
#J8Stream @JosePaumard
ZippingSpliteratorZippingSpliterator
• [1, 2, 3, …], [a, b, c, …] -> [F(1, a), F(2, b), F(3, c), …]
public boolean tryAdvance(Consumer<? super R> action) {
return spliterator1.tryAdvance(
e1 ‐> {
spliterator2.tryAdvance(e2 ‐> {
action.accept(tranform.apply(e1, e2)) ;
}) ;
}) ;
}
#J8Stream @JosePaumard
ZippingSpliteratorZippingSpliterator
• [1, 2, 3, …], [a, b, c, …] -> [F(1, a), F(2, b), F(3, c), …]
public Spliterator<R> trySplit() {
return new ZippingSpliterator<E1, E2, R>(
spliterator1.trySplit(), 
spliterator2.trySplit(), 
tranform) ;
}
public long estimateSize() {
return this.spliterator1.estimateSize() ;
}
#J8Stream @JosePaumard
PairingSpliteratorPairingSpliterator
• [1, 2, 3, …], [a, b, c, …] -> [(1, a), (2, b), (3, c), …]
public class PairingSpliterator<E1, E2> 
extends ZippingSpliterator<E1, E2, Pair<E1, E2>> {
public PairingSpliterator(
Spliterator<E1> spliterator1, Spliterator<E2> spliterator2) {
super(spliterator1, 
spliterator2, 
(e1, e2) ‐> new Pair<E1, E2>(e1, e2)) ;
}
}
}
#J8Stream @JosePaumard
Stream vs RxJavaStream vs RxJava
• Pour la partie cold : on peut l’implémenter avec des
Stream
• Pour la partie hot : on peut interfacer les deux API
#J8Stream @JosePaumard
Comparaisons
#J8Stream @JosePaumard
ComparaisonsComparaisons
• Cas applicatif unique
• Implémentés avec les trois API
• Comparaisons des patterns
• Mesure des temps de traitement avec JMH
#J8Stream @JosePaumard
Shakespeare joue an ScrabbleShakespeare joue an Scrabble
• « Shakespeare joue au Scrabble »
• Ensemble de mots
 Les mots utilisés par Shakespeare
 Les mots autorisés au Scrabble
• Question : quel aurait été le meilleur mot que
Shakespeare aurait pu jouer ?
#J8Stream @JosePaumard
Shakespeare joue an ScrabbleShakespeare joue an Scrabble
• Comparaison des principaux patterns
• Puis comparaison des performances globales
#J8Stream @JosePaumard
Histogramme des lettresHistogramme des lettres
• Java Stream GS Collections Rx Java
// Histogram of the letters in a given word
Function<String, Map<Integer, Long>> histoOfLetters = 
word ‐> word.chars().boxed()
.collect(
Collectors.groupingBy(
Function.identity(),
Collectors.counting()
)
) ;
#J8Stream @JosePaumard
Histogramme des lettresHistogramme des lettres
• Java Stream GS Collections Rx Java
// Histogram of the letters in a given word
Function<String, MutableMap<Integer, Long>> histoOfLetters = 
word ‐> new CharArrayList(word.toCharArray())
.collect(c ‐> new Integer((int)c))
// .groupBy(letter ‐> letter) ;
.aggregateBy(
letter ‐> letter, 
() ‐> 0L, 
(value, letter) ‐> { return value + 1 ; }
) ;
#J8Stream @JosePaumard
Histogramme des lettresHistogramme des lettres
• Java Stream GS Collections Rx Java
// Histogram of the letters in a given word
Func1<String, Observable<HashMap<Integer, LongWrapper>>> histoOfLetters =
word ‐> toIntegerObservable.call(word)
.collect(
() ‐> new HashMap<Integer, LongWrapper>(), 
(HashMap<Integer, LongWrapper> map, Integer value) ‐> { 
LongWrapper newValue = map.get(value) ;
if (newValue == null) {
newValue = () ‐> 0L ;
}
map.put(value, newValue.incAndSet()) ;
}) ;
#J8Stream @JosePaumard
Histogramme des lettresHistogramme des lettres
• Java Stream GS Collections Rx Java
interface LongWrapper {
long get() ;
public default LongWrapper set(long l) {
return () ‐> l ;
}
public default LongWrapper incAndSet() {
return () ‐> get() + 1L ;
}
public default LongWrapper add(LongWrapper other) {
return () ‐> get() + other.get() ;
}
}
#J8Stream @JosePaumard
Nombre de blancs pour une lettreNombre de blancs pour une lettre
• Java Stream GS Collections Rx Java
// number of blanks for a given letter
ToLongFunction<Map.Entry<Integer, Long>> blank =
entry ‐> 
Long.max(
0L, 
entry.getValue() ‐
scrabbleAvailableLetters[entry.getKey() ‐ 'a']
) ;
#J8Stream @JosePaumard
Nombre de blancs pour une lettreNombre de blancs pour une lettre
• Java Stream GS Collections Rx Java
// number of blanks for a given letter
LongFunction<Map.Entry<Integer, Long>> blank = 
entry ‐> 
Long.max(
0L, 
entry.getValue() ‐
scrabbleAvailableLetters[entry.getKey() ‐ 'a']
) ;
#J8Stream @JosePaumard
Nombre de blancs pour une lettreNombre de blancs pour une lettre
• Java Stream GS Collections Rx Java
// number of blanks for a given letter
Func1<Entry<Integer, LongWrapper>, Observable<Long>> blank =
entry ‐>
Observable.just(
Long.max(
0L, 
entry.getValue().get() ‐
scrabbleAvailableLetters[entry.getKey() ‐ 'a']
#J8Stream @JosePaumard
Nombre de blancs pour un motNombre de blancs pour un mot
• Java Stream GS Collections Rx Java
// number of blanks for a given word
Function<String, Long> nBlanks =
word ‐> histoOfLetters.apply(word)
.entrySet().stream()
.mapToLong(blank)
.sum();
#J8Stream @JosePaumard
Nombre de blancs pour un motNombre de blancs pour un mot
• Java Stream GS Collections Rx Java
// number of blanks for a given word
Function<String, Long> nBlanks =
word ‐> UnifiedSet.newSet(
histoOfLetters.valueOf(word)
.entrySet()
)
.sumOfLong(blank) ;
#J8Stream @JosePaumard
Nombre de blancs pour un motNombre de blancs pour un mot
• Java Stream GS Collections Rx Java
// number of blanks for a given word
Func1<String, Observable<Long>> nBlanks = 
word ‐> histoOfLetters.call(word)
.flatMap(map ‐> Observable.from(() ‐> map.entrySet().iterator()))
.flatMap(blank)
.reduce(Long::sum) ;
#J8Stream @JosePaumard
Prédicat sur 2 blancsPrédicat sur 2 blancs
• Java Stream GS Collections Rx Java
// can a word be written with 2 blanks?
Predicate<String> checkBlanks = word ‐> nBlanks.apply(word) <= 2 ;
// can a word be written with 2 blanks?
Predicate<String> checkBlanks = word ‐> nBlanks.valueOf(word) <= 2 ;
// can a word be written with 2 blanks?
Func1<String, Observable<Boolean>> checkBlanks = 
word ‐> nBlanks.call(word)
.flatMap(l ‐> Observable.just(l <= 2L)) ;
#J8Stream @JosePaumard
Bonus lettre doublée – 1Bonus lettre doublée – 1
• Java Stream GS Collections Rx Java
// Placing the word on the board
// Building the streams of first and last letters
Function<String, IntStream> first3 = 
word ‐> word.chars().limit(3);
#J8Stream @JosePaumard
Bonus lettre doublée – 1Bonus lettre doublée – 1
• Java Stream GS Collections Rx Java
// Placing the word on the board
// Building the streams of first and last letters
Function<String, MutableList<Integer>> first3 = 
word ‐>  new CharArrayList(word.toCharArray())
.collect(c ‐> (int)c) ;
.subList(0, Integer.min(list.size(), 3)) ;
#J8Stream @JosePaumard
Bonus lettre doublée – 1Bonus lettre doublée – 1
• Java Stream GS Collections Rx Java
// Placing the word on the board
// Building the streams of first and last letters
Func1<String, Observable<Integer>> first3 = 
word ‐> 
Observable.from(
IterableSpliterator.of(
word.chars().boxed().limit(3).spliterator()
)
) ;
#J8Stream @JosePaumard
Bonus lettre doublée – 2Bonus lettre doublée – 2
• Java Stream GS Collections Rx Java
// Bonus for double letter
ToIntFunction<String> bonusForDoubleLetter = 
word ‐> Stream.of(first3.apply(word), last3.apply(word))
.flatMapToInt(Function.identity())
.map(scoreOfALetter)
.max()
.orElse(0) ;
#J8Stream @JosePaumard
Bonus lettre doublée – 2Bonus lettre doublée – 2
• Java Stream GS Collections Rx Java
// Bonus for double letter
Function<String, MutableList<Integer>> toBeMaxed = 
word ‐> { 
MutableList<Integer> list = first3.valueOf(word) ;
list.addAll(last3.valueOf(word)) ;
return list ; 
} ;
IntFunction<String> bonusForDoubleLetter =
word ‐> toBeMaxed.valueOf(word)
.collect(scoreOfALetter)
.max() ;
#J8Stream @JosePaumard
Bonus lettre doublée – 2Bonus lettre doublée – 2
• Java Stream GS Collections Rx Java
// Bonus for double letter
Func1<String, Observable<Integer>> bonusForDoubleLetter = 
word ‐> Observable.just(first3.call(word), last3.call(word))
.flatMap(observable ‐> observable)
.flatMap(scoreOfALetter)
.reduce(Integer::max) ;
#J8Stream @JosePaumard
Score d’un motScore d’un mot
• Java Stream GS Collections Rx Java
// score of the word put on the board
Function<String, Integer> score3 =
word ‐> 
2*(score2.apply(word) 
+ bonusForDoubleLetter.applyAsInt(word))
+ (word.length() == 7 ? 50 : 0);
#J8Stream @JosePaumard
Score d’un motScore d’un mot
• Java Stream GS Collections Rx Java
// score of the word put on the board
Function<String, Integer> score3 = 
word ‐>
2*(score2.valueOf(word) 
+ bonusForDoubleLetter.intValueOf(word))
+ (word.length() == 7 ? 50 : 0);
#J8Stream @JosePaumard
Score d’un motScore d’un mot
• Java Stream GS Collections Rx Java
// score of the word put on the board
Func1<String, Observable<Integer>> score3 = 
word ‐>
Observable.just(
score2.call(word), score2.call(word), 
bonusForDoubleLetter.call(word), bonusForDoubleLetter.call(word), 
Observable.just(word.length() == 7 ? 50 : 0)
)
.flatMap(observable ‐> observable)
.reduce(Integer::sum) ;
#J8Stream @JosePaumard
Histogramme des scoresHistogramme des scores
• Java Stream GS Collections Rx Java
Function<Function<String, Integer>, Map<Integer, List<String>>>
buildHistoOnScore = 
score ‐> shakespeareWords.stream().parallel()
.filter(scrabbleWords::contains)
.filter(checkBlanks)
.collect(
Collectors.groupingBy(
score, 
() ‐> new TreeMap<>(Comparator.reverseOrder()), 
Collectors.toList()
)
) ;
#J8Stream @JosePaumard
Histogramme des scoresHistogramme des scores
• Java Stream GS Collections Rx Java
Function<
Function<String, Integer>, MutableMap<Integer, MutableList<String>>>
buildHistoOnScore = 
score ‐> shakespeareWords
.select(scrabbleWords::contains)
.select(checkBlanks)
.aggregateBy(
score, 
FastList::new, 
(list, value) ‐> { list.add(value) ; return list ; }
) ;
#J8Stream @JosePaumard
Histogramme des scoresHistogramme des scores
• Java Stream GS Collections Rx Java
Func1<Func1<String, Observable<Integer>>, Observable<TreeMap<Integer, List<String>>>> 
buildHistoOnScore =
score ‐> Observable.from(() ‐> shakespeareWords.iterator())
.filter(scrabbleWords::contains)
.filter(word ‐> checkBlanks.call(word).toBlocking().first())
.collect(
() ‐> new TreeMap<Integer, 
List<String>>(Comparator.reverseOrder()), 
(TreeMap<Integer, List<String>> map, String word) ‐> {
Integer key = score.call(word).toBlocking().first() ;
List<String> list = map.get(key) ;
if (list == null) {
list = new ArrayList<String>() ;
map.put(key, list) ;
}
list.add(word) ;
}) ;
#J8Stream @JosePaumard
Meilleurs motsMeilleurs mots
• Java Stream GS Collections Rx Java
// best key / value pairs
List<Entry<Integer, List<String>>> finalList = 
buildHistoOnScore.apply(score3).entrySet()
.stream()
.limit(3)
.collect(Collectors.toList()) ;
#J8Stream @JosePaumard
Meilleurs motsMeilleurs mots
• Java Stream GS Collections Rx Java
// best key / value pairs
MutableList<Entry<Integer, MutableList<String>>> finalList = 
new FastList<Map.Entry<Integer,MutableList<String>>>(
new TreeSortedMap<Integer, MutableList<String>>(
Comparator.reverseOrder(), 
buildHistoOnScore.valueOf(score3)
)
.entrySet()
)
.subList(0, 3) ;
#J8Stream @JosePaumard
Meilleurs motsMeilleurs mots
• Java Stream GS Collections Rx Java
// best key / value pairs
List<Entry<Integer, List<String>>> finalList2 =
buildHistoOnScore.call(score3)
.flatMap(map ‐> Observable.from(() ‐> map.entrySet().iterator()))
.take(3)
.collect(
() ‐> new ArrayList<Entry<Integer, List<String>>>(), 
(list, entry) ‐> { list.add(entry) ; }
)
.toBlocking()
.first() ;
#J8Stream @JosePaumard
Meilleurs motsMeilleurs mots
• Java Stream GS Collections Rx Java
// best key / value pairs
CountDownLatch latch = new CountDownLatch(3) ;
buildHistoOnScore.call(score3)
.flatMap(map ‐> Observable.from(() ‐> map.entrySet().iterator()))
.take(3)
.collect(
() ‐> new ArrayList<Entry<Integer, List<String>>>(), 
(list, entry) ‐> { list.add(entry) ; latch.countDown() ; }
)
.forEach(...) ;
latch.await() ;
#J8Stream @JosePaumard
1er bilan : patterns1er bilan : patterns
• Java 8 Stream donne les patterns les plus simples
#J8Stream @JosePaumard
1er bilan : patterns1er bilan : patterns
• Java 8 Stream donne les patterns les plus simples
• Java 8 Stream & GS Collections se ressemblent
#J8Stream @JosePaumard
1er bilan : patterns1er bilan : patterns
• Java 8 Stream donne les patterns les plus simples
• Java 8 Stream & GS Collections se ressemblent
• RxJava fait le choix du « tout flatMap » ce qui mène à
des patterns inutilement lourds
#J8Stream @JosePaumard
PerformancesPerformances
• Utilisation de JMH
• Outil standard de mesure de performances du JDK
• Développé dans le cadre de l’Open JDK
• Aleksey Shipilev http://shipilev.net/
• https://twitter.com/shipilev
http://openjdk.java.net/projects/code-tools/jcstress/
http://openjdk.java.net/projects/code-tools/jmh/
https://www.parleys.com/tutorial/java-microbenchmark-harness-the-lesser-two-evils
#J8Stream @JosePaumard
PerformancesPerformances
• Utilisation de JMH
• Outil standard de mesure de performances du JDK
• Développé dans le cadre de l’Open JDK
• Aleksey Shipilev http://shipilev.net/
• https://twitter.com/shipilev
http://openjdk.java.net/projects/code-tools/jcstress/
http://openjdk.java.net/projects/code-tools/jmh/
https://www.parleys.com/tutorial/java-microbenchmark-harness-the-lesser-two-evils
Aleksey Shipilëv @shipilev
Чувак из ТВ-службы пришёл отключать
антенну. Оказался масс-спектрометристом,
сцепился языком с тестем: стоят, обсуждают
девайсы. #наукоград
#J8Stream @JosePaumard
JMHJMH
• Simple à utiliser
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh‐core</artifactId>
<version>1.7</version>
</dependency>
#J8Stream @JosePaumard
JMHJMH
• État partagé entre les exécutions
@State(Scope.Benchmark)
public class ShakespearePlaysScrabble {
Set<String> scrabbleWords = null ;
Set<String> shakespeareWords = null ;
@Setup
public void init() {
scrabbleWords = Util.readScrabbleWords() ;
shakespeareWords = Util.readShakespeareWords() ;
}
}
#J8Stream @JosePaumard
JMHJMH
• Simple à mettre en œuvre
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations=5)
@Measurement(iterations=5)
@Fork(3)
public List<Entry<Integer, List<String>>> measureAverage() {
// implementation to test
}
#J8Stream @JosePaumard
JMHJMH
• Utilisation particulière
> mvn clean install
> java –jar target/benchmark.jar
#J8Stream @JosePaumard
JMHJMH
• 3 façons de mesurer les performances
 Temps moyen d’exécution
 Nombre d’exécutions par seconde
 Échantillonnage (diagramme par quantiles)
#J8Stream @JosePaumard
PerformancesPerformances
• Mesure du temps moyen
Benchmark           Mode  Cnt Score   Error Units
GSCollections avgt 100   25,392 ± 0,253  ms/op
#J8Stream @JosePaumard
PerformancesPerformances
• Mesure du temps moyen
Benchmark           Mode  Cnt Score   Error Units
GSCollections avgt 100   25,392 ± 0,253  ms/op
NonParallelStreams avgt 100   29,027 ± 0,279  ms/op
#J8Stream @JosePaumard
PerformancesPerformances
• Mesure du temps moyen
Benchmark           Mode  Cnt Score   Error Units
GSCollections avgt 100   25,392 ± 0,253  ms/op
NonParallelStreams avgt 100   29,027 ± 0,279  ms/op
RxJava avgt 100  253,788 ± 1,421  ms/op
#J8Stream @JosePaumard
PerformancesPerformances
• Mesure du temps moyen
Benchmark           Mode  Cnt Score   Error Units
GSCollections avgt 100   25,392 ± 0,253  ms/op
NonParallelStreams avgt 100   29,027 ± 0,279  ms/op
RxJava avgt 100  253,788 ± 1,421  ms/op
ParallelStreams avgt 100    7,624 ± 0,055  ms/op
#J8Stream @JosePaumard
PerformancesPerformances
• Mesure du temps moyen
• Attention à la mémoire avec GS Collections
Benchmark           Mode  Cnt Score   Error Units
GSCollections avgt 100   25,392 ± 0,253  ms/op
NonParallelStreams avgt 100   29,027 ± 0,279  ms/op
RxJava avgt 100  253,788 ± 1,421  ms/op
ParallelStreams avgt 100    7,624 ± 0,055  ms/op
#J8Stream @JosePaumard
Conclusion
#J8Stream @JosePaumard
ConclusionConclusion
• La programmation fonctionnelle est « à la mode »
• Du point de vue performance, les choses ne sont pas
si simples
• Le choix de l’API Stream : « une dose de fonctionnel »
est probablement le bon
#J8Stream @JosePaumard
ConclusionConclusion
• GS Collections : bonne API
 Beaucoup de patterns en doublon des Streams
 Compatible Java 7
• RxJava : API riche et complexe
 Approche différente, patterns complémentaires
 Attention aux performances
#J8Stream @JosePaumard
ConclusionConclusion
• Java 8 Stream
 Performante, efficace en mémoire
 Seule à offrir la parallélisation « gratuite »
 Extensible au travers des Spliterator
@JosePaumard#J8Stream
@JosePaumard#J8Stream

Contenu connexe

Tendances

Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Jean-Michel Doudoux
 
20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soatSOAT
 
Javascript pour les développeurs Java : quels sont les pièges à éviter ?
Javascript pour les développeurs Java : quels sont les pièges à éviter ?Javascript pour les développeurs Java : quels sont les pièges à éviter ?
Javascript pour les développeurs Java : quels sont les pièges à éviter ?FlorianBoulay
 
Interface fonctionnelle, Lambda expression, méthode par défaut, référence de...
Interface fonctionnelle, Lambda expression, méthode par défaut,  référence de...Interface fonctionnelle, Lambda expression, méthode par défaut,  référence de...
Interface fonctionnelle, Lambda expression, méthode par défaut, référence de...MICHRAFY MUSTAFA
 
Java (8) eXperiments - DevoxxFR 2016
Java (8) eXperiments - DevoxxFR 2016Java (8) eXperiments - DevoxxFR 2016
Java (8) eXperiments - DevoxxFR 2016François Sarradin
 
Les concepts de la programmation fonctionnelle illustrés avec java 8
Les concepts de la programmation fonctionnelle illustrés avec java 8Les concepts de la programmation fonctionnelle illustrés avec java 8
Les concepts de la programmation fonctionnelle illustrés avec java 8Yannick Chartois
 
Techday Arrow Group: Java 8
Techday Arrow Group: Java 8Techday Arrow Group: Java 8
Techday Arrow Group: Java 8Arrow Group
 
Librairies Java qui changent la vie
Librairies Java qui changent la vieLibrairies Java qui changent la vie
Librairies Java qui changent la viecluelessjoe
 
Cassandra Spark Lan Party at Devoxx France
Cassandra Spark Lan Party at Devoxx FranceCassandra Spark Lan Party at Devoxx France
Cassandra Spark Lan Party at Devoxx FranceJérémy Sevellec
 
Introduction au langage Go
Introduction au langage GoIntroduction au langage Go
Introduction au langage GoSylvain Wallez
 
Introduction à l'analyse de réseaux avec R
Introduction à l'analyse de réseaux avec RIntroduction à l'analyse de réseaux avec R
Introduction à l'analyse de réseaux avec RLaurent Beauguitte
 
Scala : programmation fonctionnelle
Scala : programmation fonctionnelleScala : programmation fonctionnelle
Scala : programmation fonctionnelleMICHRAFY MUSTAFA
 
Monitoring d'applications/environnements PHP: APM et Pinba
Monitoring d'applications/environnements PHP: APM et PinbaMonitoring d'applications/environnements PHP: APM et Pinba
Monitoring d'applications/environnements PHP: APM et PinbaPatrick Allaert
 
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...Normandy JUG
 
Javascript : fondamentaux et OOP
Javascript : fondamentaux et OOPJavascript : fondamentaux et OOP
Javascript : fondamentaux et OOPJean-Pierre Vincent
 
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009Coat::Persistent at FPW2009
Coat::Persistent at FPW2009Alexis Sukrieh
 
De java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvementsDe java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvementsDidier Plaindoux
 
Android Optimisations Greendroid
Android Optimisations GreendroidAndroid Optimisations Greendroid
Android Optimisations GreendroidGDG Nantes
 

Tendances (20)

Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016
 
20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat
 
Javascript pour les développeurs Java : quels sont les pièges à éviter ?
Javascript pour les développeurs Java : quels sont les pièges à éviter ?Javascript pour les développeurs Java : quels sont les pièges à éviter ?
Javascript pour les développeurs Java : quels sont les pièges à éviter ?
 
Interface fonctionnelle, Lambda expression, méthode par défaut, référence de...
Interface fonctionnelle, Lambda expression, méthode par défaut,  référence de...Interface fonctionnelle, Lambda expression, méthode par défaut,  référence de...
Interface fonctionnelle, Lambda expression, méthode par défaut, référence de...
 
Java (8) eXperiments - DevoxxFR 2016
Java (8) eXperiments - DevoxxFR 2016Java (8) eXperiments - DevoxxFR 2016
Java (8) eXperiments - DevoxxFR 2016
 
Les concepts de la programmation fonctionnelle illustrés avec java 8
Les concepts de la programmation fonctionnelle illustrés avec java 8Les concepts de la programmation fonctionnelle illustrés avec java 8
Les concepts de la programmation fonctionnelle illustrés avec java 8
 
Techday Arrow Group: Java 8
Techday Arrow Group: Java 8Techday Arrow Group: Java 8
Techday Arrow Group: Java 8
 
Librairies Java qui changent la vie
Librairies Java qui changent la vieLibrairies Java qui changent la vie
Librairies Java qui changent la vie
 
Cassandra Spark Lan Party at Devoxx France
Cassandra Spark Lan Party at Devoxx FranceCassandra Spark Lan Party at Devoxx France
Cassandra Spark Lan Party at Devoxx France
 
Introduction au langage Go
Introduction au langage GoIntroduction au langage Go
Introduction au langage Go
 
Ce bon vieux propel
Ce bon vieux propelCe bon vieux propel
Ce bon vieux propel
 
Introduction à l'analyse de réseaux avec R
Introduction à l'analyse de réseaux avec RIntroduction à l'analyse de réseaux avec R
Introduction à l'analyse de réseaux avec R
 
Scala : programmation fonctionnelle
Scala : programmation fonctionnelleScala : programmation fonctionnelle
Scala : programmation fonctionnelle
 
Monitoring d'applications/environnements PHP: APM et Pinba
Monitoring d'applications/environnements PHP: APM et PinbaMonitoring d'applications/environnements PHP: APM et Pinba
Monitoring d'applications/environnements PHP: APM et Pinba
 
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
 
Javascript : fondamentaux et OOP
Javascript : fondamentaux et OOPJavascript : fondamentaux et OOP
Javascript : fondamentaux et OOP
 
Programmation Fonctionnelle
Programmation FonctionnelleProgrammation Fonctionnelle
Programmation Fonctionnelle
 
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
 
De java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvementsDe java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvements
 
Android Optimisations Greendroid
Android Optimisations GreendroidAndroid Optimisations Greendroid
Android Optimisations Greendroid
 

En vedette

Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJava 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJosé Paumard
 
Quoi de neuf à Devoxx France 2017 ?
Quoi de neuf à Devoxx France 2017 ?Quoi de neuf à Devoxx France 2017 ?
Quoi de neuf à Devoxx France 2017 ?Antoine Rey
 
Spring Framework Petclinic sample application
Spring Framework Petclinic sample applicationSpring Framework Petclinic sample application
Spring Framework Petclinic sample applicationAntoine Rey
 
Autumn collection JavaOne 2014
Autumn collection JavaOne 2014Autumn collection JavaOne 2014
Autumn collection JavaOne 2014José Paumard
 
50 new things you can do with java 8
50 new things you can do with java 850 new things you can do with java 8
50 new things you can do with java 8José Paumard
 
Business intelligence v0.3
Business intelligence v0.3Business intelligence v0.3
Business intelligence v0.3Luca Mauri
 
What HTTP/2.0 Will Do For You
What HTTP/2.0 Will Do For YouWhat HTTP/2.0 Will Do For You
What HTTP/2.0 Will Do For YouMark Nottingham
 
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
 
Conference MicroServices101 - 1ere partie
Conference MicroServices101 - 1ere partieConference MicroServices101 - 1ere partie
Conference MicroServices101 - 1ere partieZenika
 
Microbox : Ma toolbox microservices - Julien Roy
Microbox : Ma toolbox microservices - Julien RoyMicrobox : Ma toolbox microservices - Julien Roy
Microbox : Ma toolbox microservices - Julien Royekino
 
Matinale DevOps / Docker
Matinale DevOps / DockerMatinale DevOps / Docker
Matinale DevOps / DockerZenika
 
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelleAgile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelleZenika
 
Introducing HTTP/2
Introducing HTTP/2Introducing HTTP/2
Introducing HTTP/2Ido Flatow
 
Séminaire en ligne - Email Kinetic - 30 Mai 2017
Séminaire en ligne - Email Kinetic - 30 Mai 2017Séminaire en ligne - Email Kinetic - 30 Mai 2017
Séminaire en ligne - Email Kinetic - 30 Mai 2017Experian
 
So, you wanna migrate to Java 9?
So, you wanna migrate to Java 9?So, you wanna migrate to Java 9?
So, you wanna migrate to Java 9?Tomek Adamczewki
 
Optimisez la performance de votre service client tout en maîtrisant votre b...
Optimisez la performance  de votre service client  tout en maîtrisant votre b...Optimisez la performance  de votre service client  tout en maîtrisant votre b...
Optimisez la performance de votre service client tout en maîtrisant votre b...Experian
 
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"UX STRAT
 
Better Product Definition with Lean UX and Design Thinking
Better Product Definition with Lean UX and Design ThinkingBetter Product Definition with Lean UX and Design Thinking
Better Product Definition with Lean UX and Design ThinkingJeff Gothelf
 
Introduction to HTTP/2
Introduction to HTTP/2Introduction to HTTP/2
Introduction to HTTP/2Ido Flatow
 

En vedette (20)

Java 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelizationJava 8, Streams & Collectors, patterns, performances and parallelization
Java 8, Streams & Collectors, patterns, performances and parallelization
 
Quoi de neuf à Devoxx France 2017 ?
Quoi de neuf à Devoxx France 2017 ?Quoi de neuf à Devoxx France 2017 ?
Quoi de neuf à Devoxx France 2017 ?
 
Spring Framework Petclinic sample application
Spring Framework Petclinic sample applicationSpring Framework Petclinic sample application
Spring Framework Petclinic sample application
 
Autumn collection JavaOne 2014
Autumn collection JavaOne 2014Autumn collection JavaOne 2014
Autumn collection JavaOne 2014
 
50 new things you can do with java 8
50 new things you can do with java 850 new things you can do with java 8
50 new things you can do with java 8
 
Business intelligence v0.3
Business intelligence v0.3Business intelligence v0.3
Business intelligence v0.3
 
What HTTP/2.0 Will Do For You
What HTTP/2.0 Will Do For YouWhat HTTP/2.0 Will Do For You
What HTTP/2.0 Will Do For You
 
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
 
Conference MicroServices101 - 1ere partie
Conference MicroServices101 - 1ere partieConference MicroServices101 - 1ere partie
Conference MicroServices101 - 1ere partie
 
Microbox : Ma toolbox microservices - Julien Roy
Microbox : Ma toolbox microservices - Julien RoyMicrobox : Ma toolbox microservices - Julien Roy
Microbox : Ma toolbox microservices - Julien Roy
 
Matinale DevOps / Docker
Matinale DevOps / DockerMatinale DevOps / Docker
Matinale DevOps / Docker
 
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelleAgile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
 
Introducing HTTP/2
Introducing HTTP/2Introducing HTTP/2
Introducing HTTP/2
 
Séminaire en ligne - Email Kinetic - 30 Mai 2017
Séminaire en ligne - Email Kinetic - 30 Mai 2017Séminaire en ligne - Email Kinetic - 30 Mai 2017
Séminaire en ligne - Email Kinetic - 30 Mai 2017
 
So, you wanna migrate to Java 9?
So, you wanna migrate to Java 9?So, you wanna migrate to Java 9?
So, you wanna migrate to Java 9?
 
Optimisez la performance de votre service client tout en maîtrisant votre b...
Optimisez la performance  de votre service client  tout en maîtrisant votre b...Optimisez la performance  de votre service client  tout en maîtrisant votre b...
Optimisez la performance de votre service client tout en maîtrisant votre b...
 
Company_Profile_Digital_1
Company_Profile_Digital_1Company_Profile_Digital_1
Company_Profile_Digital_1
 
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
UX STRAT USA: Leah Buley, "The Role of UX / CX in Business"
 
Better Product Definition with Lean UX and Design Thinking
Better Product Definition with Lean UX and Design ThinkingBetter Product Definition with Lean UX and Design Thinking
Better Product Definition with Lean UX and Design Thinking
 
Introduction to HTTP/2
Introduction to HTTP/2Introduction to HTTP/2
Introduction to HTTP/2
 

Similaire à Les Streams sont parmi nous

Oxalide Workshop #3 - Elasticearch, an overview
Oxalide Workshop #3 - Elasticearch, an overviewOxalide Workshop #3 - Elasticearch, an overview
Oxalide Workshop #3 - Elasticearch, an overviewLudovic Piot
 
Oxalide Academy : Workshop #3 Elastic Search
Oxalide Academy : Workshop #3 Elastic SearchOxalide Academy : Workshop #3 Elastic Search
Oxalide Academy : Workshop #3 Elastic SearchOxalide
 
Comprendre, utiliser et créer une API
Comprendre, utiliser et créer une APIComprendre, utiliser et créer une API
Comprendre, utiliser et créer une APIOlivia Reaney
 
Base NoSql et Python
Base NoSql et PythonBase NoSql et Python
Base NoSql et Pythonyboussard
 
MyBatis, une alternative à JPA.
MyBatis, une alternative à JPA.MyBatis, une alternative à JPA.
MyBatis, une alternative à JPA.Kokou Gaglo
 
Datamapper L Orm Dans Rails 3
Datamapper L Orm Dans Rails 3Datamapper L Orm Dans Rails 3
Datamapper L Orm Dans Rails 3Cyril Mougel
 
Analyse statistique sur DOTA
Analyse statistique sur DOTAAnalyse statistique sur DOTA
Analyse statistique sur DOTABanville Julien
 
Data Mining (Partie 2).pdf
Data Mining (Partie 2).pdfData Mining (Partie 2).pdf
Data Mining (Partie 2).pdfOuailChoukhairi
 
SplunkLive! Paris 2018: Getting Data In
SplunkLive! Paris 2018: Getting Data InSplunkLive! Paris 2018: Getting Data In
SplunkLive! Paris 2018: Getting Data InSplunk
 
Apprentissage automatique avec RapidMiner
Apprentissage automatique avec RapidMinerApprentissage automatique avec RapidMiner
Apprentissage automatique avec RapidMinerMajdi Hannachi
 
Data Modeling Power BI [SqlSat '18]
Data Modeling Power BI [SqlSat '18]Data Modeling Power BI [SqlSat '18]
Data Modeling Power BI [SqlSat '18]Joël Crest
 
ElasticSearch : Architecture et Développement
ElasticSearch : Architecture et DéveloppementElasticSearch : Architecture et Développement
ElasticSearch : Architecture et DéveloppementMohamed hedi Abidi
 
Publication des données publiques (Open Data), WCF Data Services, OData
Publication des données publiques (Open Data), WCF Data Services, ODataPublication des données publiques (Open Data), WCF Data Services, OData
Publication des données publiques (Open Data), WCF Data Services, ODataMicrosoft Ideas
 
AWS Paris Summit 2014 - T3 - Du temps réel au data warehouse : capturez et an...
AWS Paris Summit 2014 - T3 - Du temps réel au data warehouse : capturez et an...AWS Paris Summit 2014 - T3 - Du temps réel au data warehouse : capturez et an...
AWS Paris Summit 2014 - T3 - Du temps réel au data warehouse : capturez et an...Amazon Web Services
 
Découvrez le parcours de vos données : lignage de données de bout en bout ...
Découvrez le parcours de vos données : lignage de données de bout en bout ...Découvrez le parcours de vos données : lignage de données de bout en bout ...
Découvrez le parcours de vos données : lignage de données de bout en bout ...Wiiisdom
 
#HACKAGAINSTEBOLA : mise en oeuvre de prototypes rapides
#HACKAGAINSTEBOLA : mise en oeuvre de prototypes rapides#HACKAGAINSTEBOLA : mise en oeuvre de prototypes rapides
#HACKAGAINSTEBOLA : mise en oeuvre de prototypes rapidesAbdoulaye Kanté
 

Similaire à Les Streams sont parmi nous (20)

Utc data publica1
Utc data publica1Utc data publica1
Utc data publica1
 
Oxalide Workshop #3 - Elasticearch, an overview
Oxalide Workshop #3 - Elasticearch, an overviewOxalide Workshop #3 - Elasticearch, an overview
Oxalide Workshop #3 - Elasticearch, an overview
 
Oxalide Academy : Workshop #3 Elastic Search
Oxalide Academy : Workshop #3 Elastic SearchOxalide Academy : Workshop #3 Elastic Search
Oxalide Academy : Workshop #3 Elastic Search
 
Comprendre, utiliser et créer une API
Comprendre, utiliser et créer une APIComprendre, utiliser et créer une API
Comprendre, utiliser et créer une API
 
Base NoSql et Python
Base NoSql et PythonBase NoSql et Python
Base NoSql et Python
 
MyBatis, une alternative à JPA.
MyBatis, une alternative à JPA.MyBatis, une alternative à JPA.
MyBatis, une alternative à JPA.
 
Datamapper L Orm Dans Rails 3
Datamapper L Orm Dans Rails 3Datamapper L Orm Dans Rails 3
Datamapper L Orm Dans Rails 3
 
Analyse statistique sur DOTA
Analyse statistique sur DOTAAnalyse statistique sur DOTA
Analyse statistique sur DOTA
 
R versur Python
R versur PythonR versur Python
R versur Python
 
Data Mining (Partie 2).pdf
Data Mining (Partie 2).pdfData Mining (Partie 2).pdf
Data Mining (Partie 2).pdf
 
SplunkLive! Paris 2018: Getting Data In
SplunkLive! Paris 2018: Getting Data InSplunkLive! Paris 2018: Getting Data In
SplunkLive! Paris 2018: Getting Data In
 
Apprentissage automatique avec RapidMiner
Apprentissage automatique avec RapidMinerApprentissage automatique avec RapidMiner
Apprentissage automatique avec RapidMiner
 
Data Modeling Power BI [SqlSat '18]
Data Modeling Power BI [SqlSat '18]Data Modeling Power BI [SqlSat '18]
Data Modeling Power BI [SqlSat '18]
 
ElasticSearch : Architecture et Développement
ElasticSearch : Architecture et DéveloppementElasticSearch : Architecture et Développement
ElasticSearch : Architecture et Développement
 
Publication des données publiques (Open Data), WCF Data Services, OData
Publication des données publiques (Open Data), WCF Data Services, ODataPublication des données publiques (Open Data), WCF Data Services, OData
Publication des données publiques (Open Data), WCF Data Services, OData
 
Spring data
Spring dataSpring data
Spring data
 
AWS Paris Summit 2014 - T3 - Du temps réel au data warehouse : capturez et an...
AWS Paris Summit 2014 - T3 - Du temps réel au data warehouse : capturez et an...AWS Paris Summit 2014 - T3 - Du temps réel au data warehouse : capturez et an...
AWS Paris Summit 2014 - T3 - Du temps réel au data warehouse : capturez et an...
 
Découvrez le parcours de vos données : lignage de données de bout en bout ...
Découvrez le parcours de vos données : lignage de données de bout en bout ...Découvrez le parcours de vos données : lignage de données de bout en bout ...
Découvrez le parcours de vos données : lignage de données de bout en bout ...
 
Presentation JPA
Presentation JPAPresentation JPA
Presentation JPA
 
#HACKAGAINSTEBOLA : mise en oeuvre de prototypes rapides
#HACKAGAINSTEBOLA : mise en oeuvre de prototypes rapides#HACKAGAINSTEBOLA : mise en oeuvre de prototypes rapides
#HACKAGAINSTEBOLA : mise en oeuvre de prototypes rapides
 

Plus de José Paumard

Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19José Paumard
 
From Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdfFrom Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdfJosé Paumard
 
The Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern MatchingThe Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern MatchingJosé Paumard
 
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
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé Paumard
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé Paumard
 
Designing functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor PatternDesigning functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor PatternJosé Paumard
 
Construire son JDK en 10 étapes
Construire son JDK en 10 étapesConstruire son JDK en 10 étapes
Construire son JDK en 10 étapesJosé Paumard
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!José Paumard
 
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
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1José Paumard
 
Asynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowAsynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowJosé Paumard
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJosé Paumard
 
Collectors in the Wild
Collectors in the WildCollectors in the Wild
Collectors in the WildJosé Paumard
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full storyJosé Paumard
 

Plus de José Paumard (20)

Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19
 
From Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdfFrom Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdf
 
The Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern MatchingThe Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern Matching
 
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
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
Designing functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor PatternDesigning functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor Pattern
 
Construire son JDK en 10 étapes
Construire son JDK en 10 étapesConstruire son JDK en 10 étapes
Construire son JDK en 10 étapes
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!
 
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
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1
 
Asynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowAsynchronous Systems with Fn Flow
Asynchronous Systems with Fn Flow
 
Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) Bridge
 
Collectors in the Wild
Collectors in the WildCollectors in the Wild
Collectors in the Wild
 
Streams in the wild
Streams in the wildStreams in the wild
Streams in the wild
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full story
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 

Dernier

SciencesPo_Aix_InnovationPédagogique_Atelier_FormationRecherche.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_FormationRecherche.pdfSciencesPo_Aix_InnovationPédagogique_Atelier_FormationRecherche.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_FormationRecherche.pdfSKennel
 
SciencesPo_Aix_InnovationPédagogique_Atelier_EtudiantActeur.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_EtudiantActeur.pdfSciencesPo_Aix_InnovationPédagogique_Atelier_EtudiantActeur.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_EtudiantActeur.pdfSKennel
 
Cours SE Le système Linux : La ligne de commande bash - IG IPSET
Cours SE Le système Linux : La ligne de commande bash - IG IPSETCours SE Le système Linux : La ligne de commande bash - IG IPSET
Cours SE Le système Linux : La ligne de commande bash - IG IPSETMedBechir
 
Formation M2i - Comprendre les neurosciences pour développer son leadership
Formation M2i - Comprendre les neurosciences pour développer son leadershipFormation M2i - Comprendre les neurosciences pour développer son leadership
Formation M2i - Comprendre les neurosciences pour développer son leadershipM2i Formation
 
Le Lean sur une ligne de production : Formation et mise en application directe
Le Lean sur une ligne de production : Formation et mise en application directeLe Lean sur une ligne de production : Formation et mise en application directe
Le Lean sur une ligne de production : Formation et mise en application directeXL Groupe
 
Zotero avancé - support de formation doctorants SHS 2024
Zotero avancé - support de formation doctorants SHS 2024Zotero avancé - support de formation doctorants SHS 2024
Zotero avancé - support de formation doctorants SHS 2024Alain Marois
 
Cours SE Gestion des périphériques - IG IPSET
Cours SE Gestion des périphériques - IG IPSETCours SE Gestion des périphériques - IG IPSET
Cours SE Gestion des périphériques - IG IPSETMedBechir
 
Saint Georges, martyr, et la lègend du dragon.pptx
Saint Georges, martyr, et la lègend du dragon.pptxSaint Georges, martyr, et la lègend du dragon.pptx
Saint Georges, martyr, et la lègend du dragon.pptxMartin M Flynn
 
BONNES PRATIQUES DE FABRICATION RESUME SIMPLIFIE
BONNES PRATIQUES DE FABRICATION RESUME SIMPLIFIEBONNES PRATIQUES DE FABRICATION RESUME SIMPLIFIE
BONNES PRATIQUES DE FABRICATION RESUME SIMPLIFIEgharebikram98
 
SciencesPo_Aix_InnovationPédagogique_Conférence_SK.pdf
SciencesPo_Aix_InnovationPédagogique_Conférence_SK.pdfSciencesPo_Aix_InnovationPédagogique_Conférence_SK.pdf
SciencesPo_Aix_InnovationPédagogique_Conférence_SK.pdfSKennel
 
Principe de fonctionnement d'un moteur 4 temps
Principe de fonctionnement d'un moteur 4 tempsPrincipe de fonctionnement d'un moteur 4 temps
Principe de fonctionnement d'un moteur 4 tempsRajiAbdelghani
 
SciencesPo_Aix_InnovationPédagogique_Atelier_IA.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_IA.pdfSciencesPo_Aix_InnovationPédagogique_Atelier_IA.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_IA.pdfSKennel
 
Presentation de la plateforme Moodle - avril 2024
Presentation de la plateforme Moodle - avril 2024Presentation de la plateforme Moodle - avril 2024
Presentation de la plateforme Moodle - avril 2024Gilles Le Page
 
SciencesPo_Aix_InnovationPédagogique_Bilan.pdf
SciencesPo_Aix_InnovationPédagogique_Bilan.pdfSciencesPo_Aix_InnovationPédagogique_Bilan.pdf
SciencesPo_Aix_InnovationPédagogique_Bilan.pdfSKennel
 
le present des verbes reguliers -er.pptx
le present des verbes reguliers -er.pptxle present des verbes reguliers -er.pptx
le present des verbes reguliers -er.pptxmmatar2
 
Fondation Louis Vuitton. pptx
Fondation      Louis      Vuitton.   pptxFondation      Louis      Vuitton.   pptx
Fondation Louis Vuitton. pptxTxaruka
 
Evaluation du systeme d'Education. Marocpptx
Evaluation du systeme d'Education. MarocpptxEvaluation du systeme d'Education. Marocpptx
Evaluation du systeme d'Education. MarocpptxAsmaa105193
 
A3iFormations, organisme de formations certifié qualiopi.
A3iFormations, organisme de formations certifié qualiopi.A3iFormations, organisme de formations certifié qualiopi.
A3iFormations, organisme de formations certifié qualiopi.Franck Apolis
 
LA MONTÉE DE L'ÉDUCATION DANS LE MONDE DE LA PRÉHISTOIRE À L'ÈRE CONTEMPORAIN...
LA MONTÉE DE L'ÉDUCATION DANS LE MONDE DE LA PRÉHISTOIRE À L'ÈRE CONTEMPORAIN...LA MONTÉE DE L'ÉDUCATION DANS LE MONDE DE LA PRÉHISTOIRE À L'ÈRE CONTEMPORAIN...
LA MONTÉE DE L'ÉDUCATION DANS LE MONDE DE LA PRÉHISTOIRE À L'ÈRE CONTEMPORAIN...Faga1939
 
Présentation_ Didactique 1_SVT (S4) complet.pptx
Présentation_ Didactique 1_SVT (S4) complet.pptxPrésentation_ Didactique 1_SVT (S4) complet.pptx
Présentation_ Didactique 1_SVT (S4) complet.pptxrababouerdighi
 

Dernier (20)

SciencesPo_Aix_InnovationPédagogique_Atelier_FormationRecherche.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_FormationRecherche.pdfSciencesPo_Aix_InnovationPédagogique_Atelier_FormationRecherche.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_FormationRecherche.pdf
 
SciencesPo_Aix_InnovationPédagogique_Atelier_EtudiantActeur.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_EtudiantActeur.pdfSciencesPo_Aix_InnovationPédagogique_Atelier_EtudiantActeur.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_EtudiantActeur.pdf
 
Cours SE Le système Linux : La ligne de commande bash - IG IPSET
Cours SE Le système Linux : La ligne de commande bash - IG IPSETCours SE Le système Linux : La ligne de commande bash - IG IPSET
Cours SE Le système Linux : La ligne de commande bash - IG IPSET
 
Formation M2i - Comprendre les neurosciences pour développer son leadership
Formation M2i - Comprendre les neurosciences pour développer son leadershipFormation M2i - Comprendre les neurosciences pour développer son leadership
Formation M2i - Comprendre les neurosciences pour développer son leadership
 
Le Lean sur une ligne de production : Formation et mise en application directe
Le Lean sur une ligne de production : Formation et mise en application directeLe Lean sur une ligne de production : Formation et mise en application directe
Le Lean sur une ligne de production : Formation et mise en application directe
 
Zotero avancé - support de formation doctorants SHS 2024
Zotero avancé - support de formation doctorants SHS 2024Zotero avancé - support de formation doctorants SHS 2024
Zotero avancé - support de formation doctorants SHS 2024
 
Cours SE Gestion des périphériques - IG IPSET
Cours SE Gestion des périphériques - IG IPSETCours SE Gestion des périphériques - IG IPSET
Cours SE Gestion des périphériques - IG IPSET
 
Saint Georges, martyr, et la lègend du dragon.pptx
Saint Georges, martyr, et la lègend du dragon.pptxSaint Georges, martyr, et la lègend du dragon.pptx
Saint Georges, martyr, et la lègend du dragon.pptx
 
BONNES PRATIQUES DE FABRICATION RESUME SIMPLIFIE
BONNES PRATIQUES DE FABRICATION RESUME SIMPLIFIEBONNES PRATIQUES DE FABRICATION RESUME SIMPLIFIE
BONNES PRATIQUES DE FABRICATION RESUME SIMPLIFIE
 
SciencesPo_Aix_InnovationPédagogique_Conférence_SK.pdf
SciencesPo_Aix_InnovationPédagogique_Conférence_SK.pdfSciencesPo_Aix_InnovationPédagogique_Conférence_SK.pdf
SciencesPo_Aix_InnovationPédagogique_Conférence_SK.pdf
 
Principe de fonctionnement d'un moteur 4 temps
Principe de fonctionnement d'un moteur 4 tempsPrincipe de fonctionnement d'un moteur 4 temps
Principe de fonctionnement d'un moteur 4 temps
 
SciencesPo_Aix_InnovationPédagogique_Atelier_IA.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_IA.pdfSciencesPo_Aix_InnovationPédagogique_Atelier_IA.pdf
SciencesPo_Aix_InnovationPédagogique_Atelier_IA.pdf
 
Presentation de la plateforme Moodle - avril 2024
Presentation de la plateforme Moodle - avril 2024Presentation de la plateforme Moodle - avril 2024
Presentation de la plateforme Moodle - avril 2024
 
SciencesPo_Aix_InnovationPédagogique_Bilan.pdf
SciencesPo_Aix_InnovationPédagogique_Bilan.pdfSciencesPo_Aix_InnovationPédagogique_Bilan.pdf
SciencesPo_Aix_InnovationPédagogique_Bilan.pdf
 
le present des verbes reguliers -er.pptx
le present des verbes reguliers -er.pptxle present des verbes reguliers -er.pptx
le present des verbes reguliers -er.pptx
 
Fondation Louis Vuitton. pptx
Fondation      Louis      Vuitton.   pptxFondation      Louis      Vuitton.   pptx
Fondation Louis Vuitton. pptx
 
Evaluation du systeme d'Education. Marocpptx
Evaluation du systeme d'Education. MarocpptxEvaluation du systeme d'Education. Marocpptx
Evaluation du systeme d'Education. Marocpptx
 
A3iFormations, organisme de formations certifié qualiopi.
A3iFormations, organisme de formations certifié qualiopi.A3iFormations, organisme de formations certifié qualiopi.
A3iFormations, organisme de formations certifié qualiopi.
 
LA MONTÉE DE L'ÉDUCATION DANS LE MONDE DE LA PRÉHISTOIRE À L'ÈRE CONTEMPORAIN...
LA MONTÉE DE L'ÉDUCATION DANS LE MONDE DE LA PRÉHISTOIRE À L'ÈRE CONTEMPORAIN...LA MONTÉE DE L'ÉDUCATION DANS LE MONDE DE LA PRÉHISTOIRE À L'ÈRE CONTEMPORAIN...
LA MONTÉE DE L'ÉDUCATION DANS LE MONDE DE LA PRÉHISTOIRE À L'ÈRE CONTEMPORAIN...
 
Présentation_ Didactique 1_SVT (S4) complet.pptx
Présentation_ Didactique 1_SVT (S4) complet.pptxPrésentation_ Didactique 1_SVT (S4) complet.pptx
Présentation_ Didactique 1_SVT (S4) complet.pptx
 

Les Streams sont parmi nous

  • 4. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • De 1998 à 2014… seul outil : l’API Collection  Common collections
  • 5. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • De 1998 à 2014… seul outil : l’API Collection  Common collections • À partir de 2014… un foisonnement !
  • 6. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Pourquoi autant d’offres ? • Parce que le traitement de données devient central…
  • 7. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Pourquoi autant d’offres ? • Parce que le traitement de données devient central… et complexe !
  • 8. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Pourquoi autant d’offres ? • Parce que le traitement de données devient central… et complexe !  Volumes de plus en plus importants
  • 9. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Pourquoi autant d’offres ? • Parce que le traitement de données devient central… et complexe !  Volumes de plus en plus importants  Temps de réponse maîtrisés
  • 10. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Pourquoi autant d’offres ? • Parce que le traitement de données devient central… et complexe !  Volumes de plus en plus importants  Temps de réponse maîtrisés  Algorithmes complexes
  • 11. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Le traitement de données a besoin de « primitives » de haut niveau
  • 12. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Le traitement de données a besoin de « primitives » de haut niveau  Qui permettent d’accéder aux données où qu’elles soient
  • 13. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Le traitement de données a besoin de « primitives » de haut niveau  Qui permettent d’accéder aux données où qu’elles soient  Qui exposent des fonctions (map / filter / reduce)
  • 14. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Le traitement de données a besoin de « primitives » de haut niveau  Qui permettent d’accéder aux données où qu’elles soient  Qui exposent des fonctions (map / filter / reduce)  Qui soient efficaces !
  • 15. #J8Stream @JosePaumard Traitement de donnéesTraitement de données • Le traitement de données a besoin de « primitives » de haut niveau  Qui permettent d’accéder aux données où qu’elles soient  Qui exposent des fonctions (map / filter / reduce)  Qui soient efficaces !  Éventuellement parallèles
  • 16. #J8Stream @JosePaumard Objet de la présentationObjet de la présentation • Présenter trois API  Exposer les concepts fondamentaux  Présenter les fonctions implémentées  Montrer des patterns de code (Java 8, lambdas) • Comparer ces API  Point de vue de l’utilisateur  Performances !
  • 17. #J8Stream @JosePaumard Objet de la présentationObjet de la présentation • Proposer une grille de lecture et d’analyse  Comparer des outils qui proposent des solutions différentes pour un même problème
  • 18. #J8Stream @JosePaumard Objet de la présentationObjet de la présentation • Proposer une grille de lecture et d’analyse  Comparer des outils qui proposent des solutions différentes pour un même problème • Du point de vue du développeur
  • 19. #J8Stream @JosePaumard Objet de la présentationObjet de la présentation • Proposer une grille de lecture et d’analyse  Comparer des outils qui proposent des solutions différentes pour un même problème • Du point de vue du développeur  Performance  Patterns écriture / lecture
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 26. #J8Stream @JosePaumard Les forces en présenceLes forces en présence • Les 3 API sont :  L’API Stream de Java 8
  • 27. #J8Stream @JosePaumard Les forces en présenceLes forces en présence • Les 3 API sont :  L’API Stream de Java 8  GS Collections
  • 28. #J8Stream @JosePaumard Les forces en présenceLes forces en présence • Les 3 API sont :  L’API Stream de Java 8  GS Collections  RxJava
  • 29. #J8Stream @JosePaumard Les forces en présenceLes forces en présence • Les 3 API sont :  L’API Stream de Java 8  GS Collections  RxJava • Comparaison des performances sur un exemple commun
  • 31. #J8Stream @JosePaumard API StreamAPI Stream • Qu’est-ce qu’un Stream Java 8 ?  Un objet que l’on connecte à une source
  • 32. #J8Stream @JosePaumard API StreamAPI Stream • Qu’est-ce qu’un Stream Java 8 ?  Un objet que l’on connecte à une source  Un objet qui ne porte pas les données qu’il traite
  • 33. #J8Stream @JosePaumard API StreamAPI Stream • Qu’est-ce qu’un Stream Java 8 ?  Un objet que l’on connecte à une source  Un objet qui ne porte pas les données qu’il traite  Un objet qui expose le pattern map / filter / reduce
  • 34. #J8Stream @JosePaumard API StreamAPI Stream • Qu’est-ce qu’un Stream Java 8 ?  Un objet que l’on connecte à une source  Un objet qui ne porte pas les données qu’il traite  Un objet qui expose le pattern map / filter / reduce • Nouveau concept introduit dans le JDK
  • 35. #J8Stream @JosePaumard API StreamAPI Stream • Exemple List<String> liste = Arrays.asList("un", "deux", "trois") ; liste.stream()  .map(s ‐> s.toUpperCase()) .max(Comparator.comparing(s ‐> s.length())) .ifPresent(s ‐> System.out.println(s)) ;
  • 36. #J8Stream @JosePaumard API StreamAPI Stream • Exemple List<String> liste = Arrays.asList("un", "deux", "trois") ; liste.stream()  // ouverture d’un stream de String .map(s ‐> s.toUpperCase())  .max(Comparator.comparing(s ‐> s.length())) .ifPresent(s ‐> System.out.println(s)) ;
  • 37. #J8Stream @JosePaumard API StreamAPI Stream • Exemple List<String> liste = Arrays.asList("un", "deux", "trois") ; liste.stream() .map(s ‐> s.toUpperCase()) // mise en majuscules des éléments .max(Comparator.comparing(s ‐> s.length())) .ifPresent(s ‐> System.out.println(s)) ;
  • 38. #J8Stream @JosePaumard API StreamAPI Stream • Exemple List<String> liste = Arrays.asList("un", "deux", "trois") ; liste.stream() .map(s ‐> s.toUpperCase()) .max(Comparator.comparing(s ‐> s.length())) // plus longue .ifPresent(s ‐> System.out.println(s)) ;
  • 39. #J8Stream @JosePaumard API StreamAPI Stream • Exemple List<String> liste = Arrays.asList("un", "deux", "trois") ; liste.stream() .map(s ‐> s.toUpperCase()) .max(Comparator.comparing(s ‐> s.length())) .ifPresent(s ‐> System.out.println(s)) ; // Optional !
  • 40. #J8Stream @JosePaumard API StreamAPI Stream • Exemple List<String> liste = Arrays.asList("un", "deux", "trois") ; liste.stream() .map(String::toUpperCase) .max(Comparator.comparing(String::length) .ifPresent(System.out::println) ; // Optional !
  • 41. #J8Stream @JosePaumard CollectorsCollectors • On peut collecter des données List<Person> liste = ... ; liste.stream() .filter(person ‐> person.getAge() > 30) .collect( Collectors.groupingBy( Person::getAge,       // key extractor Collectors.counting() // downstream collector ) ) ;
  • 42. #J8Stream @JosePaumard CollectorsCollectors • On peut collecter des données List<Person> liste = ... ; liste.stream() .filter(person ‐> person.getAge() > 30) .collect( Collectors.groupingBy( Person::getAge,       // key extractor Collectors.counting() // downstream collector ) ) ;
  • 43. #J8Stream @JosePaumard CollectorsCollectors • On peut collecter des données List<Person> liste = ... ; Map<Integer, Long> map =  liste.stream() .filter(person ‐> person.getAge() > 30) .collect( Collectors.groupingBy( Person::getAge,       // key extractor Collectors.counting() // downstream collector ) ) ;
  • 44. #J8Stream @JosePaumard CollectorsCollectors • Et on peut paralléliser les traitements List<Person> liste = ... ; Map<Integer, Long> map =  liste.stream().parallel() .filter(person ‐> person.getAge() > 30) .collect( Collectors.groupingBy( Person::getAge,       // key extractor Collectors.counting() // downstream collector ) ) ;
  • 45. #J8Stream @JosePaumard Particularisation d’un StreamParticularisation d’un Stream • On peut le connecter à sa propre source de données  Implémenter un Spliterator (~ Iterator)
  • 46. #J8Stream @JosePaumard Particularisation d’un StreamParticularisation d’un Stream • On peut le connecter à sa propre source de données  Implémenter un Spliterator (~ Iterator) • On peut implémenter son propre Collector
  • 48. #J8Stream @JosePaumard IntroductionIntroduction • API Open source, Github • Développé par Goldman Sachs • Contribution importante https://github.com/goldmansachs/gs-collections
  • 49. #J8Stream @JosePaumard GS CollectionsGS Collections • Une alternative à l’API Collection  Parfois très ressemblante… • Des interfaces supplémentaires  Beaucoup !  Des méthodes supplémentaires sur les interfaces existantes
  • 50. #J8Stream @JosePaumard GS CollectionsGS Collections • Nouveaux concepts ?
  • 51. #J8Stream @JosePaumard GS CollectionsGS Collections • Nouveaux concepts ? • Oui et non…
  • 52. #J8Stream @JosePaumard GS CollectionsGS Collections • Nouveaux concepts ? • Oui et non…  Bag
  • 53. #J8Stream @JosePaumard GS CollectionsGS Collections • Nouveaux concepts ? • Oui et non…  Bag  MultiMap
  • 54. #J8Stream @JosePaumard GS CollectionsGS Collections • Nouveaux concepts ? • Oui et non…  Bag  MultiMap  MutableSet
  • 55. #J8Stream @JosePaumard GS CollectionsGS Collections • Nouveaux concepts ? • Plutôt des extensions des concepts de l’API Collection
  • 56. #J8Stream @JosePaumard GS CollectionsGS Collections • Nouveaux concepts ? • Plutôt des extensions des concepts de l’API Collection  Certains sont dans Common collections ou Guava
  • 57. #J8Stream @JosePaumard Structures fondamentalesStructures fondamentales • Bag = Collection • Existe en plusieurs couleurs !
  • 58. #J8Stream @JosePaumard Structures fondamentalesStructures fondamentales • Bag = Collection • Existe en plusieurs couleurs ! • Primitifs : IntBag, LongBag, …
  • 59. #J8Stream @JosePaumard Structures fondamentalesStructures fondamentales • Bag = Collection • Existe en plusieurs couleurs ! • Primitifs : IntBag, LongBag, … • ImmutableBag, MutableBag
  • 60. #J8Stream @JosePaumard Structures fondamentalesStructures fondamentales • Bag = Collection • Existe en plusieurs couleurs ! • Primitifs : IntBag, LongBag, … • ImmutableBag, MutableBag • Sorted, Unsorted
  • 61. #J8Stream @JosePaumard Structures fondamentalesStructures fondamentales • Bag = Collection • Existe en plusieurs couleurs ! • Primitifs : IntBag, LongBag, … • ImmutableBag, MutableBag • Sorted, Unsorted • Synchronized
  • 62. #J8Stream @JosePaumard Structures fondamentalesStructures fondamentales • Bag, List, Set, Stack, Map, Multimap
  • 63. #J8Stream @JosePaumard Structures fondamentalesStructures fondamentales • Bag, List, Set, Stack, Map, Multimap • Nombreuses implémentations
  • 64. #J8Stream @JosePaumard BagBag • Méthodes originales type Collection Bag<Person> bag = ... ; int numberOfPaul = bag.occurenceOf(paul) ;
  • 65. #J8Stream @JosePaumard BagBag • Méthodes originales type Collection Bag<Person> bag = ... ; int numberOfPaul = bag.occurenceOf(paul) ; int numberOfDistinct = bag.sizeDistinct() ;
  • 66. #J8Stream @JosePaumard BagBag • Méthodes originales type Collection Bag<Person> bag = ... ; int numberOfPaul = bag.occurenceOf(paul) ; int numberOfDistinct = bag.sizeDistinct() ; Bag<Customer> customers = bag.instanceOf(Customer.class) ;
  • 67. #J8Stream @JosePaumard BagBag • Méthodes originales type Collection Bag<Person> bag = ... ; Partition<Person> partition =  bag.partition(person ‐> person.getAge() > 30) ;
  • 68. #J8Stream @JosePaumard BagBag • Méthodes originales type Collection Bag<Person> bag = ... ; Partition<Person> partition =  bag.partition(person ‐> person.getAge() > 30) ; Bag<Person> selected = partition.getSelected() ; Bag<Person> rejected = partition.getRejected() ;
  • 69. #J8Stream @JosePaumard BagBag • Méthodes originales type Collection Bag<Person> bag = ... ; Partition<Person> partition =  bag.partition(person ‐> person.getAge() > 30) ; Bag<Person> selected = partition.getSelected() ; Bag<Person> rejected = partition.getRejected() ; Bag<Person> selected = bag.select(person ‐> person.getAge() > 30) ; Bag<Person> rejected = bag.reject(person ‐> person.getAge() > 30) ;
  • 70. #J8Stream @JosePaumard BagBag • Méthode forEach() Bag<Person> bag = ... ; bag.forEach(System.out::println) ;
  • 71. #J8Stream @JosePaumard BagBag • Méthode forEach() Bag<Person> bag = ... ; bag.forEach(System.out::println) ; // compiler error
  • 72. #J8Stream @JosePaumard BagBag • Méthode forEach() Bag<Person> bag = ... ; bag.forEach(System.out::println) ; // compiler error public interface Iterable<T> { // java.util default void forEach(Consumer<? super T> action) {...} }
  • 73. #J8Stream @JosePaumard BagBag • Méthode forEach() Bag<Person> bag = ... ; bag.forEach(System.out::println) ; // compiler error public interface InternalIterable<T> { // GS Collection  void forEach(Procedure<? super T> procedure) ; }
  • 74. #J8Stream @JosePaumard BagBag • Méthode forEach() Bag<Person> bag = ... ; bag.forEach((Procedure<String>)System.out::println) ;
  • 75. #J8Stream @JosePaumard BagBag • Méthodes map & filter Bag<Person> bag = ... ; Bag<String> names = bag.collect(Person::getAge) ;      // eq. map() Bag<String> names = bag.select(p ‐> p.getAge() > 30) ; // eq filter()
  • 76. #J8Stream @JosePaumard BagBag • Méthodes map & filter Bag<Person> bag = ... ; Bag<String> names = bag.collect(Person::getAge) ;      // eq. map() Bag<String> names = bag.select(p ‐> p.getAge() > 30) ; // eq filter() Bag<T> tap(Procedure<? super T> procedure) ;
  • 77. #J8Stream @JosePaumard BagBag • Méthodes map & flatMap Bag<T> collect( // eq. map() Function<? super T, ? extends V> function) {...} Bag<T> flatCollect( // eq. flatMap() Function<? super T, ? extends Iterable<V>> function) {...}
  • 78. #J8Stream @JosePaumard BagBag • Méthodes map & filter fusionnées Bag<Person> bag = ... ; names = bag.collectIf(person ‐> person.getAge() > 30,  Peson::getName) ;
  • 79. #J8Stream @JosePaumard BagBag • Méthodes de réduction Bag<Person> bag = ... ; boolean b1 = bag.allSatisfy(person ‐> person.getAge() > 30) ; boolean b2 = bag.anySatisfy(person ‐> person.getAge() > 100) ; boolean b3 = bag.noneSatisfy(person ‐> person.getAge() < 18) ;
  • 80. #J8Stream @JosePaumard BagBag • Méthodes de réduction Bag<Person> bag = ... ; Person first = bag.detect( person ‐> person.getAge() > 30) ; Person p = bag.detectIfNone( person ‐> person.getAge() > 100,  () ‐> Person.NOBODY) ;
  • 81. #J8Stream @JosePaumard BagBag • Méthodes de réduction Bag<Person> bag = ... ; Person first = bag.detectWith( (person, param) ‐> person.getAge() > param,  30) ; Person p = bag.detectWithIfNone( (person, param) ‐> person.getAge() > param,  100,  () ‐> Person.NOBODY) ;
  • 82. #J8Stream @JosePaumard BagBag • Méthodes de folding Bag<Person> bag = ... ; long sum = bag.injectInto( 0L,  (sum, person) ‐> sum + person.getAge()) ; long count = bag.injectInto( 0L,  (sum, person) ‐> sum + 1L) ;
  • 83. #J8Stream @JosePaumard BagBag • Méthodes de folding Bag<Person> bag = ... ; long sum = bag.injectInto( 0L,  (l, person) ‐> l + person.getAge()) ; long sumOfAge = bag.sumOfInt(Person::getAge)) ;
  • 84. #J8Stream @JosePaumard BagBag • Méthodes de folding Bag<Person> bag = ... ; String names = bag.collect(Person::getName).makeString() ; Charles, Michelle, Paul, Barbara
  • 85. #J8Stream @JosePaumard BagBag • Réduction dans une chaîne de caractères Bag<Person> bag = ... ; String names = bag.collect(Person::getAge).makeString() ; String names = bag.collect(Person::getAge).makeString(" ; ") ; Charles ; Michelle ; Paul ; Barbara
  • 86. #J8Stream @JosePaumard BagBag • Réduction dans une chaîne de caractères Bag<Person> bag = ... ; String names = bag.collect(Person::getAge).makeString() ; String names = bag.collect(Person::getAge).makeString(" ; ") ; String names = bag.collect(Person::getAge).makeString("{", " ; ", "}") ; {Charles ; Michelle ; Paul ; Barbara}
  • 87. #J8Stream @JosePaumard BagBag • Réduction dans une chaîne de caractères Bag<Person> bag = ... ; bag.collect(Person::getAge) .appendString(StringBuilder::new) ;
  • 88. #J8Stream @JosePaumard BagBag • Réduction dans une table de hachage Bag<Person> bag = ... ; MapIterable<Integer, Bag<Person>> map =  bag.aggregateBy( Person::getAge,       // key extractor FastList::new,        // zero factory (list, person) ‐> {   // list.add(person) ; // merge operation return list ;      // } ) ;
  • 89. #J8Stream @JosePaumard BagBag • Réduction dans une table de hachage Bag<Person> bag = ... ; MultiMap<Integer, Person> map = bag.groupBy(Person::getAge) ;
  • 90. #J8Stream @JosePaumard MutableMapMutableMap • Méthodes de Map V getIfAbsentPut(K key,  Function0<? extends V> function) ; V getIfAbsentPutWithKey(K key,  Function<? super K, ? extends V> function) ; V getIfAbsentPutWith(K key,  Function<? super P, ? extends V> function P parameter) ;
  • 91. #J8Stream @JosePaumard MutableMapMutableMap • Méthodes forEach() void forEachKeyValue(Procedure2<? super K, ? super V> procedure) ; void forEachKey(Procedure<? super T> procedure) ; void forEachValue(Procedure<? super T> procedure) ;
  • 92. #J8Stream @JosePaumard MutableMapMutableMap • Méthodes map • Une table de hachage est aussi une liste de valeurs MapIterable<K2, V2>  collect(Function2<? super K, ? super V, Pair<K2, V2>> function) ; public interface MapIterable<K, V> extends RichIterable<V> { }
  • 93. #J8Stream @JosePaumard PairPair • Modélisation d’un tuple public interface Pair<T1, T2> extends Serializable, Comparable<Pair<T1, T2>> { T1 getOne(); T2 getTwo(); void put(Map<T1, T2> map); Map.Entry<T1, T2> toEntry(); // pont avec API Collection  Pair<T2, T1> swap(); }
  • 94. #J8Stream @JosePaumard MutableMapMutableMap • Les méthodes map, filter et méthodes de réduction sont définies sur RichIterable  Donc disponibles sur les tables de hachage  Elles opèrent sur les valeurs • Méthodes groupBy, retournent de nouvelles tables reject(Predicate2<? super K, ? super V> predicate) ; select(Predicate2<? super K, ? super V> predicate) ;
  • 95. #J8Stream @JosePaumard ImmutableMapImmutableMap • Méthodes pour « ajouter » des clés / valeurs MutableMapIterable<K, V> withKeyValue(K key, V value) ; // put MutableMapIterable<K, V> withoutKey(K key) ; // remove
  • 96. #J8Stream @JosePaumard MultiMapMultiMap • Concept qui ne fait pas partie de l’API Collection • Map qui associe plusieurs valeurs à une même clé  Gère une collection de valeurs en interne MultiMap<Integer, Person> map ;  // GS Collections Map<Integer, List<Person>> map ; // API Collection
  • 97. #J8Stream @JosePaumard MultiMapMultiMap • La plupart des méthodes sont les mêmes • Méthodes get différentes RichIterable<V> values = multiMap.get(K key) ; MutableMap<K, RichIterable<V>> map = multiMap.toMap() ;
  • 98. #J8Stream @JosePaumard Structures concurrentesStructures concurrentes • ConcurrentHashMap  Construite sur un tableau de Entry (AtomicReferenceArray)  Accès via des AtomicReference  Même structure que java.util.HashMap
  • 99. #J8Stream @JosePaumard Opérations de type ZipOpérations de type Zip • Permet d’appairer deux ensembles Bag<Person> bag1 = ImmutableBagImpl.of(anna, charles) ; Bag<Person> bag2 = ImmutableBagImpl.of(paul, barbara) ; Bag<Pair<Person, Person>> friends = bag1.zip(bag2) ;
  • 100. #J8Stream @JosePaumard Opérations de type ZipOpérations de type Zip • Permet d’appairer deux ensembles Bag<Person> bag1 = ImmutableBagImpl.of(anna, charles) ; Bag<Person> bag2 = ImmutableBagImpl.of(paul, barbara) ; Bag<City> bag3 = ImmutableBagImpl.of(paris, sanFrancisco) ; Bag<Pair<Person, Person>> friends = bag1.zip(bag2) ; Bag<Pair<Person, City>> living = bag1.zip(bag3) ;
  • 101. #J8Stream @JosePaumard Opérations de type ZipOpérations de type Zip • Permet d’appairer deux ensembles Bag<Person> bag1 = ImmutableBagImpl.of(anna, charles) ; Bag<Person> bag2 = ImmutableBagImpl.of(paul, barbara) ; Bag<City> bag3 = ImmutableBagImpl.of(paris, sanFrancisco) ; Bag<Pair<Person, Person>> friends = bag1.zip(bag2) ; Bag<Pair<Person, City>> living = bag1.zip(bag3) ; Bag<Pair<City, Integer>> cities = bag3.zipWithIndex() ;
  • 102. #J8Stream @JosePaumard Classes factoryClasses factory • Factory pour Bag, List, Set, Stack, Map Bag<Long> bagOfInteger = MutableBagFactoryImpl.of(1L, 2L, 5L) ; Bag<Person> bagOfPerson = MutableBagFactoryImpl.of(persons) ;
  • 103. #J8Stream @JosePaumard ImplémentationsImplémentations • Pas de miracle à attendre… // class FastList public boolean add(T newItem) { if (this.items.length == this.size) { this.ensureCapacityForAdd(); } this.items[this.size++] = newItem; return true; }
  • 104. #J8Stream @JosePaumard ImplémentationsImplémentations • Pas de miracle à attendre… // class FastList public boolean add(T newItem) { if (this.items.length == this.size) { this.ensureCapacityForAdd(); } this.items[this.size++] = newItem; return true; } // class ArrayList public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; }
  • 105. #J8Stream @JosePaumard ImplémentationsImplémentations • Une implémentation est différente : celle des tables de hachage  Fonctionne avec un tableau unique
  • 106. #J8Stream @JosePaumard BizarreriesBizarreries • Quelques bizarreries MutableMap<K, V> map1 = map.asUnmodifiable() ; // UnmodifiableMap ?
  • 107. #J8Stream @JosePaumard Bilan sur l’APIBilan sur l’API • Une API complète (complexe) • Concept de MultiMap • Des méthodes que l’on trouve sur Stream  Ajoutées aux collections • Des méthodes supplémentaires  Que l’on aura peut-être sur Stream (zip)
  • 109. #J8Stream @JosePaumard RxJavaRxJava • API Open source, Github • Développé par Netflix • Version Java de ReactiveX  .NET  Python, Kotlin, JavaScript, Scala, Ruby, Groovy, Rust  Android https://github.com/ReactiveX/RxJava
  • 110. #J8Stream @JosePaumard Vue d’ensembleVue d’ensemble • Approche différente de GS Collections • Il ne s’agit pas d’une implémentation alternative de l’API Collection • Mais plutôt de l’implémentation du pattern Reactor
  • 111. #J8Stream @JosePaumard Pattern ReactorPattern Reactor • Set (fixed size, mutable, immutable, primitifs) • SortedSet (fixed size, mutable, immutable, primitifs) • Pool • Stack (mutable, immutable, primitifs) http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf
  • 112. #J8Stream @JosePaumard Notions fondamentalesNotions fondamentales • Observable : source de données
  • 113. #J8Stream @JosePaumard Notions fondamentalesNotions fondamentales • Observable : source de données  Objet complexe ~100 méthodes statiques + ~150 méthodes non statiques
  • 114. #J8Stream @JosePaumard Notions fondamentalesNotions fondamentales • Observable : source de données  Objet complexe ~100 méthodes statiques + ~150 méthodes non statiques • Observer : permet d’observer un observable  Objet simple : 3 méthodes
  • 115. #J8Stream @JosePaumard Notions fondamentalesNotions fondamentales • Observable : source de données  Objet complexe ~100 méthodes statiques + ~150 méthodes non statiques • Observer : permet d’observer un observable  Objet simple : 3 méthodes • Subscription : lien qui existe entre un observable et un observer
  • 116. #J8Stream @JosePaumard Notions fondamentalesNotions fondamentales • Observer public interface Observer<T> { public void onNext(T t); public void onCompleted(); public void onError(Throwable e); }
  • 117. #J8Stream @JosePaumard Notions fondamentalesNotions fondamentales • Associer un observer à un observable Observable<T> observable = ... ; Subscription subscription = observable.subscribe(observer) ; public interface Subscription { public void unsubscribe(); public void isUnsubscribe(); }
  • 118. #J8Stream @JosePaumard Création d’un ObservableCréation d’un Observable • Constructeur non vide protégé
  • 119. #J8Stream @JosePaumard Création d’un ObservableCréation d’un Observable • Constructeur non vide protégé • On peut construire un Observable  par extension  en utilisant une des méthodes statiques
  • 120. #J8Stream @JosePaumard Création d’un ObservableCréation d’un Observable • Constructeur non vide protégé • On peut construire un Observable  par extension  en utilisant une des méthodes statiques • Prend un producer en paramètre
  • 121. #J8Stream @JosePaumard Création d’un ObservableCréation d’un Observable • Création à partir de collections Observable<String> obs1 = Observable.just("one",  "two", "three") ; List<String> strings = Arrays.asList("one",  "two", "three") ; Observable<String> obs2 = Observable.from(strings) ;
  • 122. #J8Stream @JosePaumard Création d’un ObservableCréation d’un Observable • Création à partir de collections Observable<String> obs1 = Observable.just("one",  "two", "three") ; List<String> strings = Arrays.asList("one",  "two", "three") ; Observable<String> obs2 = Observable.from(strings) ; Observable<String> empty = Observable.empty() ; Observable<String> never = Observable.never() ; Observable<String> error = Observable.<String>error(exception) ;
  • 123. #J8Stream @JosePaumard Création d’un ObservableCréation d’un Observable • Création de séries Observable<Long> longs = Observable.range(1L, 100L) ;
  • 124. #J8Stream @JosePaumard Création d’un ObservableCréation d’un Observable • Création de séries Observable<Long> longs = Observable.range(1L, 100L) ; // interval Observable<Long> timeSerie1 =  Observable.interval(1L, TimeUnit.MILLISECONDS) ; // a serie of longs // initial delay, then interval Observable<Long> timeSerie2 =  Observable.timer(10L, 1L, TimeUnit.MILLISECONDS) ; // one 0
  • 125. #J8Stream @JosePaumard Création d’un ObservableCréation d’un Observable • Méthode using() public final static <T, Resource> Observable<T> using( final Func0<Resource> resourceFactory, // producer final Func1<Resource, Observable<T>> observableFactory, // function final Action1<? super Resource> disposeAction // consumer ) { }
  • 126. #J8Stream @JosePaumard Notion de SchedulerNotion de Scheduler • Ces méthodes peuvent prendre un autre paramètre • Scheduler : interface • Associée à la factory Schedulers Observable<Long> longs = Observable.range(0L, 100L, scheduler) ;
  • 127. #J8Stream @JosePaumard Notion de SchedulerNotion de Scheduler • Factory Schedulers public final class Schedulers { public static Scheduler immediate() {...}   // immediate, same thread public static Scheduler newThread() {...}   // new thread public static Scheduler computation() {...} // computation ES public static Scheduler io() {...}          // IO growing ES }
  • 128. #J8Stream @JosePaumard Notion de SchedulerNotion de Scheduler • Factory Schedulers public final class Schedulers { public static Scheduler trampoline() {...} // queued in the current // thread public static Scheduler test() {...} public static Scheduler fromExecutor(Executor executor) {...} }
  • 129. #J8Stream @JosePaumard Notion de SchedulerNotion de Scheduler • RxJava permet de créer des Observable dans différents threads • Certains pools sont spécialisés : IO, Computation • On peut passer ses propres pools • Les observateurs sont appelés dans les threads des observables
  • 130. #J8Stream @JosePaumard Notion de SchedulerNotion de Scheduler • La classe Scheduler n’est pas immédiate à étendre • On utilise from() pour les threads IHM (Swing, JavaFX)
  • 132. @JosePaumard Pause café ! #J8Stream Encore du RxJava Patterns Extensions de Stream Performance
  • 134. #J8Stream @JosePaumard Observable : méthodes statiquesObservable : méthodes statiques • Série de méthodes statiques de combinaisons d’Observable en un seul
  • 135. #J8Stream @JosePaumard Observable de listesObservable de listes • amb() : prend une liste d’Observable et suit le premier qui parle ©RxJava O1 O2 O1
  • 136. #J8Stream @JosePaumard Observable de listesObservable de listes • combineLatest() : applique une fonction aux deux derniers éléments émis ©RxJava O1 O2 F(O1, O2)
  • 137. #J8Stream @JosePaumard Observable de listesObservable de listes • zip() : équivalent d’un combine, mais prend les éléments un par un ©RxJava O1 O2 F(O1, O2)
  • 138. #J8Stream @JosePaumard Observable de listesObservable de listes • concat() : émet O1 puis O2, sans les mélanger • merge() : émet O1 et O2, s’arrête sur erreur
  • 139. #J8Stream @JosePaumard Observable de listesObservable de listes • concat() : émet O1 puis O2, sans les mélanger • merge() : émet O1 et O2, s’arrête sur erreur ©RxJava©RxJava
  • 140. #J8Stream @JosePaumard Observable de listesObservable de listes • concat() : émet O1 puis O2, sans les mélanger • merge() : émet O1 et O2, s’arrête avec le premier • mergeDelayError() : reporte l’erreur à la fin ©RxJava
  • 141. #J8Stream @JosePaumard Observable de listesObservable de listes • sequenceEqual() : compare deux séquences ©RxJava O1 O2 boolean
  • 142. #J8Stream @JosePaumard Observable d’ObservableObservable d’Observable • switchOnNext() : un peu spécial…
  • 143. #J8Stream @JosePaumard Observable d’ObservableObservable d’Observable • Paramètres des méthodes précédentes : public final static <T> Observable<T> merge( Iterable<Observable<T>> listOfSequences) { }
  • 144. #J8Stream @JosePaumard Observable d’ObservableObservable d’Observable • Paramètres des méthodes précédentes : public final static <T> Observable<T> merge( Iterable<Observable<T>> listOfSequences) { } public final static <T> Observable<T> merge( Observable<Observable<T>> sequenceOfSequences) { }
  • 145. #J8Stream @JosePaumard Observable d’ObservableObservable d’Observable • Paramètres des méthodes précédentes : public final static <T> Observable<T> merge( Iterable<Observable<T>> listOfSequences) { } ©RxJava
  • 146. #J8Stream @JosePaumard Observable d’ObservableObservable d’Observable • Paramètres des méthodes précédentes : public final static <T> Observable<T> merge( Observable<Observable<T>> sequenceOfSequences) { } ©RxJava
  • 147. #J8Stream @JosePaumard Observable d’ObservableObservable d’Observable • switchOnNext() : prend le nouvel Observable ©RxJava public final static <T> Observable<T> switchOnNext( Observable<Observable<T>> sequenceOfSequences) { }
  • 148. #J8Stream @JosePaumard ExemplesExemples • Un petit cas simple Observable<Integer> range1To100 = Observable.range(1L, 100L) ; manyStrings.subscribe(System.out::println) ;
  • 149. #J8Stream @JosePaumard ExemplesExemples • Un petit cas simple Observable<Integer> range1To100 = Observable.range(1L, 100L) ; manyStrings.subscribe(System.out::println) ; > 1 2 3 4 ... 100
  • 150. #J8Stream @JosePaumard ExemplesExemples • Un petit cas un peu plus dur Observable<Integer> timer = Observable.timer(1, TimeUnit.SECONDS) ; timer.subscribe(System.out::println) ;
  • 151. #J8Stream @JosePaumard ExemplesExemples • Un petit cas un peu plus dur • N’affiche rien… Observable<Integer> timer = Observable.timer(1, TimeUnit.SECONDS) ; timer.subscribe(System.out::println) ; >
  • 152. #J8Stream @JosePaumard ExemplesExemples • Un petit cas un peu plus dur Observable<Integer> timer = Observable.timer(1, TimeUnit.SECONDS) ; timer.subscribe(() ‐> { System.out.println(Thread.currentThread().getName() + " " +  Thread.currentThread().isDaemon()) ; }) ; Thread.sleep(2) ;
  • 153. #J8Stream @JosePaumard ExemplesExemples • Un petit cas un peu plus dur Observable<Integer> timer = Observable.timer(1, TimeUnit.SECONDS) ; timer.subscribe(() ‐> { System.out.println(Thread.currentThread().getName() + " " +  Thread.currentThread().isDaemon()) ; }) ; Thread.sleep(2) ; > RxComputationThreadPool‐1 ‐ true
  • 154. #J8Stream @JosePaumard ExemplesExemples • Encore un peu plus dur Observable<Integer> range1To100 = Observable.range(1, 100) ; Observable<String> manyStrings =  Observable.combineLatest( range1To100, Observable.just("one"), (integer, string) ‐> string) ;
  • 155. #J8Stream @JosePaumard ExemplesExemples • Encore un peu plus dur Observable<Integer> range1To100 = Observable.range(1, 100) ; Observable<String> manyStrings =  Observable.combineLatest( range1To100, Observable.just("one"), (integer, string) ‐> string) ; > one (et c’est tout) Combines two source Observables  by emitting an item that aggregates the latest values of each of the  source Observables  each time an item is received from  either of the source Observables,  where this aggregation is defined by  a specified function. 
  • 156. #J8Stream @JosePaumard ExemplesExemples • Encore un peu plus dur Observable<Integer> serie = Observable.interval(3, TimeUnit.MILLISECONDS) ; Observable<String> manyStrings =  Observable.combineLatest( serie, Observable.just("one"), (integer, string) ‐> string) ;
  • 157. #J8Stream @JosePaumard ExemplesExemples • Encore un peu plus dur Observable<Integer> serie = Observable.interval(3, TimeUnit.MILLISECONDS) ; Observable<String> manyStrings =  Observable.combineLatest( serie, Observable.just("one"), (integer, string) ‐> string) ; > one one one one one one ...
  • 158. #J8Stream @JosePaumard Observables hot & coldObservables hot & cold • Deux mécanismes d’Observable :  Ceux qui émettent des données lorsqu’elles sont consommées = cold observables  Ceux qui émettent des données, qu’elles soient consommées ou pas = hot observables • Un hot observable peut générer ses données indépendamment de ses observateurs
  • 160. #J8Stream @JosePaumard Opérations callbackOpérations callback • Retournent un Observable<T> • ~10 versions doOn* doOnNext(Action1<T> onNext) { } // consumer
  • 161. #J8Stream @JosePaumard Opérations booléennesOpérations booléennes • Retournent un Observable<Boolean> • Retournent un Observable<T> vide ou singleton exists(Func1<T, Boolean> predicate) { } elementAt(int index) { } ignoreElement() { }                     // returns an empty Observable single() { }                            // completes on error or transmits single(Func1<T, Boolean> predicate) { } // returns the item or error
  • 162. #J8Stream @JosePaumard Opérations de mappingOpérations de mapping • Retournent un Observable<R> map(Func1<T, R> mapping) { }  cast(Class<R> clazz) { } // casts the elements timestamp() { }  // wraps the elements in a timestamped object zipWith(Observable<U> other,  Func2<T, U, R> zipFunction) { } // BiFunction flatMap(Func1<T, Observable<R>> mapping) { }
  • 163. #J8Stream @JosePaumard Opérations de filtrageOpérations de filtrage • Retourne un Observable<T> filter(Func1<T, Boolean> predicate) { } 
  • 164. #J8Stream @JosePaumard Opérations de sélectionOpérations de sélection • Retournent un Observable<R> sample(long period, TimeUnit timeUnit) { } ©RxJava O1 sampler
  • 165. #J8Stream @JosePaumard Opérations de sélectionOpérations de sélection • Retournent un Observable<R> sample(Observable<U> sampler) { } // samples on emission & completion ©RxJava O1 sampler
  • 166. #J8Stream @JosePaumard Remarque sur le tempsRemarque sur le temps • RxJava peut mesurer le temps « en réel » • Peut aussi utiliser un Observable comme mesure du temps  Appels à onNext() et onComplete()
  • 167. #J8Stream @JosePaumard Sélection d’élémentsSélection d’éléments • Retournent Observable<T> • Exception en cas de timeout entre deux émissions first() { } last() { } skip(int n) { } limit(int n) { } take(int n) { } timeout(long n, TimeUnit timeUnit) { } timeout(Func0<Observable<U>> firstTimeoutSelector,   // producer Func1<T, Observable<V>> timeoutSelector) { } // function
  • 168. #J8Stream @JosePaumard Méthodes de réductionMéthodes de réduction • Retourne un Observable<> singleton • Retourne un Observable<T> all(Func1<T, Boolean> predicate) { }   // Observable<Boolean> count() { }  // Observable<Long> reduce(Func2<T, T, T> accumulator) { } // Observable<T> scan(Func2<T, T, T> accumulator) { } // Observable<T> forEach(Action1<T> consumer) { }  // void
  • 169. #J8Stream @JosePaumard Méthodes de collectionMéthodes de collection • Méthode collect collect(Func0<R> stateFactory, // producer Action2<R, T> collector) { } // BiConsumer
  • 170. #J8Stream @JosePaumard Méthodes de collectionMéthodes de collection • Méthode collect • Construit une Map<T, List<String>> collect(Func0<R> stateFactory, // producer Action2<R, T> collector) { } // BiConsumer collect(() ‐> new ArrayList<String>(), // producer ArrayList::add) { } // BiConsumer
  • 171. #J8Stream @JosePaumard Méthodes de collectionMéthodes de collection • Retournent des Observable<> singleton toList() { }       // Observable<List<T>> toSortedList() { } // Observable<List<T>> toMultimap(Func1<T, K> keySelector,       // Observable< Func1<T, V> valueSelector) { } //    Map<K, Collection<T>> toMap(Func1<T, K> keySelector) { } // Observable<Map<K, T>>
  • 172. #J8Stream @JosePaumard Opérations join / groupJoinOpérations join / groupJoin • Retourne un Observable<GroupedObservable<K, T>> • GroupedObservable : observable avec une clé groupBy(Func1<T, K> keySelector) { } // function
  • 173. #J8Stream @JosePaumard Opérations join / groupJoinOpérations join / groupJoin • Combine deux observables, sur un timer public final <T2, D1, D2, R> Observable<R>  groupJoin( Observable<T2> right,  Func1<T, Observable<D1>> leftDuration, // function Func1<T2, Observable<D2>> rightDuration, // function Func2<T, Observable<T2>, R> resultSelector // bifunction ) { }
  • 174. #J8Stream @JosePaumard Opérations join / groupJoinOpérations join / groupJoin • Les fenêtres de temps sont définies par des observables  Elles démarrent lorsque l’observable démarre  Et se ferment lorsque l’observable émet un objet ou s’arrête
  • 175. #J8Stream @JosePaumard Opérations join / groupJoinOpérations join / groupJoin • Combine deux observables
  • 176. #J8Stream @JosePaumard Méthodes de debugMéthodes de debug • Deux méthodes, font du mapping • Notification : objet qui englobe des meta-données en plus materialize() { } // Observable<Notification<T>>
  • 177. #J8Stream @JosePaumard Méthodes de debugMéthodes de debug • Deux méthodes, font du mapping • Notification : objet qui englobe des métadonnées en plus des objets de l’Observable materialize() { } // Observable<Notification<T>> dematerialize() { } // Observable<T>
  • 178. #J8Stream @JosePaumard Méthodes synchronesMéthodes synchrones • Associent des opérations avec une horloge delay(long delay, TimeUnit timeUnit) ; // Observable<T>
  • 179. #J8Stream @JosePaumard Méthodes synchronesMéthodes synchrones • Associent des opérations avec une horloge • Ou avec un autre Observable delay(long delay, TimeUnit timeUnit) ; // Observable<T> delay(Func1<T, Observable<U> func1) ; // Observable<T>
  • 180. #J8Stream @JosePaumard Méthodes synchronesMéthodes synchrones • Limite le nombre d’éléments émis debounce(long delay, TimeUnit timeUnit) ; // Observable<T> ©RxJava
  • 181. #J8Stream @JosePaumard Méthodes synchronesMéthodes synchrones • Limite le nombre d’éléments émis • Peut aussi se caler sur les événements d’un Observable debounce(long delay, TimeUnit timeUnit) ; // Observable<T> debounce(Func1<T, Observable<U> func1) ;  // Observable<T>
  • 182. #J8Stream @JosePaumard Méthodes synchronesMéthodes synchrones • Mesure du temps entre événements • TimeInterval : wrapper pour la durée en ms et la valeur émise timeInterval() { } // Observable<TimeInterval<T>>
  • 183. #J8Stream @JosePaumard Méthodes synchronesMéthodes synchrones • Méthodes throttle() throttleFirst(long windowDuration, TimeUnit unit) { } // Observable<T> throttleLast(long windowDuration, TimeUnit unit) { } throttleWithTimeout(long windowDuration, TimeUnit unit) { }
  • 185. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Problème : une source peut générer « trop » d’éléments  Par rapport à la vitesse des consommateurs • Certaines méthodes permettent de « sauter » des éléments
  • 186. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Problème : une source peut émettre « trop » d’éléments  Par rapport à la vitesse des consommateurs • Ne peut pas arriver avec les cold observables
  • 187. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Problème : une source peut émettre « trop » d’éléments  Par rapport à la vitesse des consommateurs • Ne peut pas arriver avec les cold observables • Un observable cold peut devenir hot…
  • 188. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Certaines méthodes permettent de « sauter » des éléments
  • 189. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Certaines méthodes permettent de « sauter » des éléments • Backpressure : consiste à ralentir le rythme d’émission
  • 190. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Méthodes utiles : sample() et debounce() • Méthode buffer() : stocke les éléments avant de les émettre
  • 191. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Méthodes buffer() buffer(int size) { }                     // Observable<List<T>>
  • 192. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Méthodes buffer() buffer(int size) { }                     // Observable<List<T>> buffer(long timeSpan, TimeUnit unit) { } // Observable<List<T>> buffer(long timeSpan, TimeUnit unit, int maxSize) { }
  • 193. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Méthodes buffer() buffer(int size) { }                     // Observable<List<T>> buffer(long timeSpan, TimeUnit unit) { } // Observable<List<T>> buffer(long timeSpan, TimeUnit unit, int maxSize) { } buffer(Observable<O> bufferOpenings,               // Openings events Func1<O, Observable<C>> bufferClosings) { } // Closings events
  • 194. #J8Stream @JosePaumard Méthodes backpressureMéthodes backpressure • Méthodes window() window(int size) { }                     // Observable<Observable<T>> window(long timeSpan, TimeUnit unit) { } // Observable<Observable<T>> window(long timeSpan, TimeUnit unit, int maxSize) { } window(Observable<O> bufferOpenings,               // Openings events Func1<O, Observable<C>> bufferClosings) { } // Closings events
  • 195. #J8Stream @JosePaumard Méthodes repeat & retryMéthodes repeat & retry • repeat() : répète l’émission d’objets indéfiniment repeat() { }            // Observable<T> repeat(long times) { } // Observable<T>
  • 196. #J8Stream @JosePaumard Méthodes repeat & retryMéthodes repeat & retry • repeat() : répète l’émission d’objets indéfiniment • Quand l’observable appelle onComplete(), le notification handler est invoqué repeat() { }            // Observable<T> repeat(long times) { } // Observable<T> repeatWhen( Func1<Observable<Void>>, Observable<?>> notificationHandler ) { }
  • 197. #J8Stream @JosePaumard Méthodes repeat & retryMéthodes repeat & retry • repeat() : répète l’émission d’objets indéfiniment • Sur cet Observable, le notification handler peut alors invoquer :  onComplete() ou onError(), ce qui déclenche le même appel sur l’Observable source  onNext(), ce qui déclenche la répétition
  • 198. #J8Stream @JosePaumard Méthodes repeat & retryMéthodes repeat & retry • retry() : répète l’émission d’objets sur erreur retry() { }            // Observable<T> retry(long times) { } // Observable<T>
  • 199. #J8Stream @JosePaumard Méthodes repeat & retryMéthodes repeat & retry • retry() : répète l’émission d’objets sur erreur • Quand l’observable appelle onError(), le notification handler est invoqué avec l’exception retry() { }            // Observable<T> retry(long times) { } // Observable<T> retryWhen( Func1<Observable<Throwable>>, Observable<?>> notificationHandler ) { }
  • 200. #J8Stream @JosePaumard Méthodes repeat & retryMéthodes repeat & retry • Sur cet Observable, le notification handler peut alors invoquer :  onComplete() ou onError(), ce qui déclenche le même appel sur l’Observable source  onNext(), ce qui déclenche la répétition
  • 201. #J8Stream @JosePaumard Plusieurs ObserverPlusieurs Observer • À la différence des Stream de Java 8, un Observable peut avoir plusieurs observateurs
  • 202. #J8Stream @JosePaumard Plusieurs ObserverPlusieurs Observer • À la différence des Stream de Java 8, un Observable peut avoir plusieurs observateurs • Ce qui peut poser des problèmes…
  • 203. #J8Stream @JosePaumard Plusieurs ObserverPlusieurs Observer • Cas d’un cold Observable :  La consommation par plusieurs observateurs ne pose pas de problème • Cas d’un hot Observable :  Un deuxième observateur peut « manquer » les premières valeurs
  • 204. #J8Stream @JosePaumard Plusieurs ObserverPlusieurs Observer • Méthode cache() • Permet de ne pas « manquer » les premières valeurs cache() { } cache(int capacity) { }
  • 205. #J8Stream @JosePaumard Plusieurs ObserverPlusieurs Observer • Notion de ConnectableObserver Observable<T> observable = ... ; ConnectableObservable<T> connectable = observable.publish() ;
  • 206. #J8Stream @JosePaumard Plusieurs ObserverPlusieurs Observer • Notion de ConnectableObserver • L’enregistrement d’observateurs ne déclenche pas la production des éléments Observable<T> observable = ... ; ConnectableObservable<T> connectable = observable.publish() ;
  • 207. #J8Stream @JosePaumard Plusieurs ObserverPlusieurs Observer • Notion de ConnectableObserver • L’enregistrement d’observateurs ne déclenche pas la production des éléments • Pour cela : appeler connect() Observable<T> observable = ... ; ConnectableObservable<T> connectable = observable.publish() ; connectable.publish() ;
  • 208. #J8Stream @JosePaumard Bilan sur RxJavaBilan sur RxJava • API Complète (complexe) • Permet de gérer le lancement de traitements dans différents pools de threads
  • 209. #J8Stream @JosePaumard Bilan sur RxJavaBilan sur RxJava • API Complète (complexe) • Permet de gérer le lancement de traitements dans différents pools de threads • Permet de synchroniser les opérations  Sur une horloge  Sur des références applicatives
  • 210. #J8Stream @JosePaumard Ponts entre Java 8 Stream / GS Collections / RxJava
  • 211. #J8Stream @JosePaumard Le meilleur des deux mondes ?Le meilleur des deux mondes ? • Connecter GS Collections et Java 8 Stream ? = connecter Stream et Iterable
  • 212. #J8Stream @JosePaumard Le meilleur des deux mondes ?Le meilleur des deux mondes ? • Connecter GS Collections et Java 8 Stream ? = connecter Stream et Iterable • Connecter Java 8 Stream et RxJava ? = connecter Stream et Observable
  • 213. #J8Stream @JosePaumard Spliterator et IteratorSpliterator et Iterator • Les collections sont construites sur des Iterator • Les Stream sont construits sur des Spliterator Iterator<T> iterator = ... ; Spliterator<T> spliterator =  Spliterators.spliteratorUnknownSize(iterator, 0) ; Spliterator<T> spliterator =  Spliterators.spliterator(iterator, size, 0) ;
  • 214. #J8Stream @JosePaumard Spliterator et IteratorSpliterator et Iterator • Les collections sont construites sur des Iterator • Les Stream sont construits sur des Spliterator Spliterator<T> spliterator = ... ; Iterator<T> iterator = Spliterators.iterator(spliterator) ; Iterator<T> iterator = ... ; Iterable<T> iterable = () ‐> iterator ;
  • 215. #J8Stream @JosePaumard GS Collections & StreamGS Collections & Stream • Le problème consiste à passer d’une Collection à un Stream (et réciproquement)
  • 216. #J8Stream @JosePaumard GS Collections & StreamGS Collections & Stream • Le problème consiste à passer d’une Collection à un Stream (et réciproquement) • Donc d’un Iterator à un Spliterator (et réciproquement)
  • 217. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Si l’on a un Iterator : facile ! Iterator<T> iterator = ... ; Observable<T> observable = Observable.from(() ‐> iterator) ;
  • 218. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Si l’on a un Iterator : facile ! • Si l’on a un Spliterator : facile ! Iterator<T> iterator = ... ; Observable<T> observable = Observable.from(() ‐> iterator) ; Spliterator<T> spliterator = ... ; Observable<T> observable =  Observable.from(() ‐> Spliterators.iterator(spliterator)) ;
  • 219. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Donc si l’on a un Stream, on peut facilement construire un Observable
  • 220. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Donc si l’on a un Stream, on peut facilement construire un Observable • L’inverse ?
  • 221. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Donc si l’on a un Stream, on peut facilement construire un Observable • L’inverse ?  On peut construire un Iterator sur un Observable  Puis un Spliterator sur un Iterator
  • 222. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Implémenter un Iterator :  Deux méthodes next() et hasNext()  La méthode remove() et une méthode par défaut
  • 223. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Un Iterator « tire » les données d’une source • Alors qu’un Observable « pousse » les données vers des callbacks
  • 224. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Un Iterator « tire » les données d’une source • Alors qu’un Observable « pousse » les données vers des callbacks • Il nous faut donc une adaptation entre les deux
  • 225. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • On peut s’inspirer du JDK public static<T> Iterator<T>  iterator(Spliterator<? extends T> spliterator) { class Adapter implements Iterator<T>, Consumer<T> { // implementation } return new Adapter() ; }
  • 226. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • On peut s’inspirer du JDK class Adapter implements Iterator<T>, Consumer<T> { boolean valueReady = false ; T nextElement; public void accept(T t) { valueReady = true ; nextElement = t ; } public boolean hasNext() { if (!valueReady) spliterator.tryAdvance(this) ; // calls accept() return valueReady ; } public T next() { if (!valueReady && !hasNext()) throw new NoSuchElementException() ; else { valueReady = false ; return nextElement ; } } }
  • 227. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • On peut s’inspirer du JDK public static<T> Iterator<T>  of(Observable<? extends T> obsevable) { class Adapter implements Iterator<T> { // implementation } return new Adapter() ; }
  • 228. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • On peut s’inspirer du JDK class Adapter implements Iterator<T>, Consumer<T> { boolean valueReady = false ; T nextElement; public void accept(T t) { valueReady = true ; nextElement = t ; } public boolean hasNext() { return valueReady ; } public T next() { if (!valueReady && !hasNext()) throw new NoSuchElementException() ; else { valueReady = false ; return nextElement ; } } }
  • 229. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • On peut s’inspirer du JDKclass Adapter implements Iterator<T>, Consumer<T> { boolean valueReady = false ; T nextElement; public void accept(T t) { observable.subscribe( element ‐> nextElement = element, // onNext exception ‐> valueReady = false,    // onError () ‐> valueReady = false            // onComplete ) ; } // next // hasNext }
  • 230. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • On peut s’inspirer du JDKclass Adapter implements Iterator<T>, Consumer<T> { AtomicBoolean valueReady = new AtomicBoolean(false) ; AtomicReference<T> nextElement = new AtomicReference() ; public void accept(T t) { observable.subscribe( element ‐> nextElement.set(element), // onNext exception ‐> valueReady.set(false),    // onError () ‐> valueReady.set(false) // onComplete ) ; } // next // hasNext }
  • 231. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Peut mieux faire ? interface Wrapper<E> { E get() ; } Wrapper<Boolean> wb = () ‐> true ;
  • 232. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Peut mieux faire ? interface Wrapper<E> { E get() ; } Wrapper<Boolean> wb = () ‐> true ; Action1<Boolean> onNext = b ‐> wb.set(b) ; // should return Wrapper<T>
  • 233. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Peut mieux faire ? interface Wrapper<E> { E get() ; public default Wrapper<E> set(E e) { // should return e } } Wrapper<Boolean> wb = () ‐> true ; Action1<Boolean> onNext = b ‐> wb.set(b) ; // should return Wrapper<T>
  • 234. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • Peut mieux faire ? interface Wrapper<E> { E get() ; public default Wrapper<E> set(E e) { return () ‐> e ; } } Wrapper<Boolean> wb = () ‐> true ; Action1<Boolean> onNext = b ‐> wb.set(b) ; // should return Wrapper<T>
  • 235. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • On peut s’inspirer du JDKclass Adapter implements Iterator<T>, Consumer<T> { Wrapper<Boolean> valueReady = () ‐> false ; Wrapper<T> nextElement ; public void accept(T t) { observable.subscribe( element ‐> nextElement.set(element), // onNext exception ‐> valueReady.set(false),    // onError () ‐> valueReady.set(false) // onComplete ) ; } // next // hasNext }
  • 236. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • On peut construire un Iterator sur un Observable  Et donc un Spliterator sur un Observable
  • 237. #J8Stream @JosePaumard RxJava & StreamRxJava & Stream • On peut construire un Iterator sur un Observable  Et donc un Spliterator sur un Observable • Fonctionne sur les cold Observable
  • 238. #J8Stream @JosePaumard Spliterators avancésSpliterators avancés • Peut-on construire des Stream à la façon des Observable ? • Partant d’un Stream [1, 2, 3, 4, 5, …]
  • 239. #J8Stream @JosePaumard Spliterators avancésSpliterators avancés • Peut-on construire des Stream à la façon des Observable ? • Partant d’un Stream [1, 2, 3, 4, 5, …]  [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] ?
  • 240. #J8Stream @JosePaumard Spliterators avancésSpliterators avancés • Peut-on construire des Stream à la façon des Observable ? • Partant d’un Stream [1, 2, 3, 4, 5, …]  [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] ?  [[1, 2, 3], [2, 3, 4], [3, 4, 5], …] ?
  • 241. #J8Stream @JosePaumard Spliterators avancésSpliterators avancés • Peut-on construire des Stream à la façon des Observable ? • Deux Stream [10, 11, 12, …] et [50, 51, 52, …]
  • 242. #J8Stream @JosePaumard Spliterators avancésSpliterators avancés • Peut-on construire des Stream à la façon des Observable ? • Deux Stream [10, 11, 12, …] et [50, 51, 52, …]  [10, 50, 11, 51, 12, 52, …] ?
  • 243. #J8Stream @JosePaumard Spliterators avancésSpliterators avancés • Peut-on construire des Stream à la façon des Observable ? • Deux Stream [10, 11, 12, …] et [50, 51, 52, …]  [10, 50, 11, 51, 12, 52, …] ?  [Pair(10, 50), Pair(11, 51), Pair(12, 52), …] ?
  • 244. #J8Stream @JosePaumard Spliterators avancésSpliterators avancés • Trois méthodes pour un Spliterator  tryAdvance(Consumer)  trySplit(), retourne un sous-spliterator  estimateSize()
  • 245. #J8Stream @JosePaumard GroupingSpliteratorGroupingSpliterator • [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] public class GroupingSpliterator<E> implements Spliterator<Stream<E>> { private final long grouping ; private final Spliterator<E> spliterator ; // implementation }
  • 246. #J8Stream @JosePaumard GroupingSpliteratorGroupingSpliterator • [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] public boolean tryAdvance(Consumer<? super Stream<E>> action) { boolean finished = false ; Stream.Builder<E> builder = Stream.builder() ; for (int i = 0 ; i < grouping ; i++) { if (!spliterator.tryAdvance(element ‐> { builder.add(element) ; })) { finished = true ; } } Stream<E> subStream = subBuilder.build() ; action.accept(subStream) ; return !finished ; }
  • 247. #J8Stream @JosePaumard GroupingSpliteratorGroupingSpliterator • [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] public Spliterator<Stream<E>> trySplit() { Spliterator<E> spliterator = this.spliterator.trySplit() ; return new GroupingSpliterator<E>(spliterator, grouping) ; }
  • 248. #J8Stream @JosePaumard GroupingSpliteratorGroupingSpliterator • [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] public long estimateSize() { return spliterator.estimateSize() / grouping ; }
  • 249. #J8Stream @JosePaumard RollingSpliteratorRollingSpliterator • [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [2, 3, 4], [3, 4, 5], …]
  • 250. #J8Stream @JosePaumard RollingSpliteratorRollingSpliterator • [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] public class RollingSpliterator<E> implements Spliterator<Stream<E>> { private final int grouping ; private final Spliterator<E> spliterator ; private Object [] buffer ; // we cant create arrays of E private AtomicInteger bufferWriteIndex = new AtomicInteger(0) ; private AtomicInteger bufferReadIndex = new AtomicInteger(0) ; // implementation }
  • 251. #J8Stream @JosePaumard RollingSpliteratorRollingSpliterator • [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] public boolean tryAdvance(Consumer<? super Stream<E>> action) { boolean finished = false ; if (bufferWriteIndex.get() == bufferReadIndex.get()) { for (int i = 0 ; i < grouping ; i++) { if (!advanceSpliterator()) { finished = true ; } } } if (!advanceSpliterator()) { finished = true ; } Stream<E> subStream = buildSubstream() ; action.accept(subStream) ; return !finished ; }
  • 252. #J8Stream @JosePaumard RollingSpliteratorRollingSpliterator • [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] private boolean advanceSpliterator() { return spliterator.tryAdvance( element ‐> {  buffer[bufferWriteIndex.get() % buffer.length] = element ;  bufferWriteIndex.incrementAndGet() ; }); }
  • 253. #J8Stream @JosePaumard RollingSpliteratorRollingSpliterator • [1, 2, 3, 4, 5, …] -> [[1, 2, 3], [4, 5, 6], [7, 8, 9], …] public Spliterator<Stream<E>> trySplit() { return new RollingSpliterator<E>(spliterator.trySplit(), grouping) ; } public long estimateSize() { return spliterator.estimateSize() ‐ grouping ; }
  • 254. #J8Stream @JosePaumard ZippingSpliteratorZippingSpliterator • [1, 2, 3, …], [a, b, c, …] -> [F(1, a), F(2, b), F(3, c), …] public class ZippingSpliterator<E1, E2, R> implements Spliterator<R> { private final Spliterator<E1> spliterator1 ; private final Spliterator<E2> spliterator2 ; private final BiFunction<E1, E2, R> tranform ; // implementation }
  • 255. #J8Stream @JosePaumard ZippingSpliteratorZippingSpliterator • [1, 2, 3, …], [a, b, c, …] -> [F(1, a), F(2, b), F(3, c), …] public boolean tryAdvance(Consumer<? super R> action) { return spliterator1.tryAdvance( e1 ‐> { spliterator2.tryAdvance(e2 ‐> { action.accept(tranform.apply(e1, e2)) ; }) ; }) ; }
  • 256. #J8Stream @JosePaumard ZippingSpliteratorZippingSpliterator • [1, 2, 3, …], [a, b, c, …] -> [F(1, a), F(2, b), F(3, c), …] public Spliterator<R> trySplit() { return new ZippingSpliterator<E1, E2, R>( spliterator1.trySplit(),  spliterator2.trySplit(),  tranform) ; } public long estimateSize() { return this.spliterator1.estimateSize() ; }
  • 257. #J8Stream @JosePaumard PairingSpliteratorPairingSpliterator • [1, 2, 3, …], [a, b, c, …] -> [(1, a), (2, b), (3, c), …] public class PairingSpliterator<E1, E2>  extends ZippingSpliterator<E1, E2, Pair<E1, E2>> { public PairingSpliterator( Spliterator<E1> spliterator1, Spliterator<E2> spliterator2) { super(spliterator1,  spliterator2,  (e1, e2) ‐> new Pair<E1, E2>(e1, e2)) ; } } }
  • 258. #J8Stream @JosePaumard Stream vs RxJavaStream vs RxJava • Pour la partie cold : on peut l’implémenter avec des Stream • Pour la partie hot : on peut interfacer les deux API
  • 260. #J8Stream @JosePaumard ComparaisonsComparaisons • Cas applicatif unique • Implémentés avec les trois API • Comparaisons des patterns • Mesure des temps de traitement avec JMH
  • 261. #J8Stream @JosePaumard Shakespeare joue an ScrabbleShakespeare joue an Scrabble • « Shakespeare joue au Scrabble » • Ensemble de mots  Les mots utilisés par Shakespeare  Les mots autorisés au Scrabble • Question : quel aurait été le meilleur mot que Shakespeare aurait pu jouer ?
  • 262. #J8Stream @JosePaumard Shakespeare joue an ScrabbleShakespeare joue an Scrabble • Comparaison des principaux patterns • Puis comparaison des performances globales
  • 263. #J8Stream @JosePaumard Histogramme des lettresHistogramme des lettres • Java Stream GS Collections Rx Java // Histogram of the letters in a given word Function<String, Map<Integer, Long>> histoOfLetters =  word ‐> word.chars().boxed() .collect( Collectors.groupingBy( Function.identity(), Collectors.counting() ) ) ;
  • 264. #J8Stream @JosePaumard Histogramme des lettresHistogramme des lettres • Java Stream GS Collections Rx Java // Histogram of the letters in a given word Function<String, MutableMap<Integer, Long>> histoOfLetters =  word ‐> new CharArrayList(word.toCharArray()) .collect(c ‐> new Integer((int)c)) // .groupBy(letter ‐> letter) ; .aggregateBy( letter ‐> letter,  () ‐> 0L,  (value, letter) ‐> { return value + 1 ; } ) ;
  • 265. #J8Stream @JosePaumard Histogramme des lettresHistogramme des lettres • Java Stream GS Collections Rx Java // Histogram of the letters in a given word Func1<String, Observable<HashMap<Integer, LongWrapper>>> histoOfLetters = word ‐> toIntegerObservable.call(word) .collect( () ‐> new HashMap<Integer, LongWrapper>(),  (HashMap<Integer, LongWrapper> map, Integer value) ‐> {  LongWrapper newValue = map.get(value) ; if (newValue == null) { newValue = () ‐> 0L ; } map.put(value, newValue.incAndSet()) ; }) ;
  • 266. #J8Stream @JosePaumard Histogramme des lettresHistogramme des lettres • Java Stream GS Collections Rx Java interface LongWrapper { long get() ; public default LongWrapper set(long l) { return () ‐> l ; } public default LongWrapper incAndSet() { return () ‐> get() + 1L ; } public default LongWrapper add(LongWrapper other) { return () ‐> get() + other.get() ; } }
  • 267. #J8Stream @JosePaumard Nombre de blancs pour une lettreNombre de blancs pour une lettre • Java Stream GS Collections Rx Java // number of blanks for a given letter ToLongFunction<Map.Entry<Integer, Long>> blank = entry ‐>  Long.max( 0L,  entry.getValue() ‐ scrabbleAvailableLetters[entry.getKey() ‐ 'a'] ) ;
  • 268. #J8Stream @JosePaumard Nombre de blancs pour une lettreNombre de blancs pour une lettre • Java Stream GS Collections Rx Java // number of blanks for a given letter LongFunction<Map.Entry<Integer, Long>> blank =  entry ‐>  Long.max( 0L,  entry.getValue() ‐ scrabbleAvailableLetters[entry.getKey() ‐ 'a'] ) ;
  • 269. #J8Stream @JosePaumard Nombre de blancs pour une lettreNombre de blancs pour une lettre • Java Stream GS Collections Rx Java // number of blanks for a given letter Func1<Entry<Integer, LongWrapper>, Observable<Long>> blank = entry ‐> Observable.just( Long.max( 0L,  entry.getValue().get() ‐ scrabbleAvailableLetters[entry.getKey() ‐ 'a']
  • 270. #J8Stream @JosePaumard Nombre de blancs pour un motNombre de blancs pour un mot • Java Stream GS Collections Rx Java // number of blanks for a given word Function<String, Long> nBlanks = word ‐> histoOfLetters.apply(word) .entrySet().stream() .mapToLong(blank) .sum();
  • 271. #J8Stream @JosePaumard Nombre de blancs pour un motNombre de blancs pour un mot • Java Stream GS Collections Rx Java // number of blanks for a given word Function<String, Long> nBlanks = word ‐> UnifiedSet.newSet( histoOfLetters.valueOf(word) .entrySet() ) .sumOfLong(blank) ;
  • 272. #J8Stream @JosePaumard Nombre de blancs pour un motNombre de blancs pour un mot • Java Stream GS Collections Rx Java // number of blanks for a given word Func1<String, Observable<Long>> nBlanks =  word ‐> histoOfLetters.call(word) .flatMap(map ‐> Observable.from(() ‐> map.entrySet().iterator())) .flatMap(blank) .reduce(Long::sum) ;
  • 273. #J8Stream @JosePaumard Prédicat sur 2 blancsPrédicat sur 2 blancs • Java Stream GS Collections Rx Java // can a word be written with 2 blanks? Predicate<String> checkBlanks = word ‐> nBlanks.apply(word) <= 2 ; // can a word be written with 2 blanks? Predicate<String> checkBlanks = word ‐> nBlanks.valueOf(word) <= 2 ; // can a word be written with 2 blanks? Func1<String, Observable<Boolean>> checkBlanks =  word ‐> nBlanks.call(word) .flatMap(l ‐> Observable.just(l <= 2L)) ;
  • 274. #J8Stream @JosePaumard Bonus lettre doublée – 1Bonus lettre doublée – 1 • Java Stream GS Collections Rx Java // Placing the word on the board // Building the streams of first and last letters Function<String, IntStream> first3 =  word ‐> word.chars().limit(3);
  • 275. #J8Stream @JosePaumard Bonus lettre doublée – 1Bonus lettre doublée – 1 • Java Stream GS Collections Rx Java // Placing the word on the board // Building the streams of first and last letters Function<String, MutableList<Integer>> first3 =  word ‐>  new CharArrayList(word.toCharArray()) .collect(c ‐> (int)c) ; .subList(0, Integer.min(list.size(), 3)) ;
  • 276. #J8Stream @JosePaumard Bonus lettre doublée – 1Bonus lettre doublée – 1 • Java Stream GS Collections Rx Java // Placing the word on the board // Building the streams of first and last letters Func1<String, Observable<Integer>> first3 =  word ‐>  Observable.from( IterableSpliterator.of( word.chars().boxed().limit(3).spliterator() ) ) ;
  • 277. #J8Stream @JosePaumard Bonus lettre doublée – 2Bonus lettre doublée – 2 • Java Stream GS Collections Rx Java // Bonus for double letter ToIntFunction<String> bonusForDoubleLetter =  word ‐> Stream.of(first3.apply(word), last3.apply(word)) .flatMapToInt(Function.identity()) .map(scoreOfALetter) .max() .orElse(0) ;
  • 278. #J8Stream @JosePaumard Bonus lettre doublée – 2Bonus lettre doublée – 2 • Java Stream GS Collections Rx Java // Bonus for double letter Function<String, MutableList<Integer>> toBeMaxed =  word ‐> {  MutableList<Integer> list = first3.valueOf(word) ; list.addAll(last3.valueOf(word)) ; return list ;  } ; IntFunction<String> bonusForDoubleLetter = word ‐> toBeMaxed.valueOf(word) .collect(scoreOfALetter) .max() ;
  • 279. #J8Stream @JosePaumard Bonus lettre doublée – 2Bonus lettre doublée – 2 • Java Stream GS Collections Rx Java // Bonus for double letter Func1<String, Observable<Integer>> bonusForDoubleLetter =  word ‐> Observable.just(first3.call(word), last3.call(word)) .flatMap(observable ‐> observable) .flatMap(scoreOfALetter) .reduce(Integer::max) ;
  • 280. #J8Stream @JosePaumard Score d’un motScore d’un mot • Java Stream GS Collections Rx Java // score of the word put on the board Function<String, Integer> score3 = word ‐>  2*(score2.apply(word)  + bonusForDoubleLetter.applyAsInt(word)) + (word.length() == 7 ? 50 : 0);
  • 281. #J8Stream @JosePaumard Score d’un motScore d’un mot • Java Stream GS Collections Rx Java // score of the word put on the board Function<String, Integer> score3 =  word ‐> 2*(score2.valueOf(word)  + bonusForDoubleLetter.intValueOf(word)) + (word.length() == 7 ? 50 : 0);
  • 282. #J8Stream @JosePaumard Score d’un motScore d’un mot • Java Stream GS Collections Rx Java // score of the word put on the board Func1<String, Observable<Integer>> score3 =  word ‐> Observable.just( score2.call(word), score2.call(word),  bonusForDoubleLetter.call(word), bonusForDoubleLetter.call(word),  Observable.just(word.length() == 7 ? 50 : 0) ) .flatMap(observable ‐> observable) .reduce(Integer::sum) ;
  • 283. #J8Stream @JosePaumard Histogramme des scoresHistogramme des scores • Java Stream GS Collections Rx Java Function<Function<String, Integer>, Map<Integer, List<String>>> buildHistoOnScore =  score ‐> shakespeareWords.stream().parallel() .filter(scrabbleWords::contains) .filter(checkBlanks) .collect( Collectors.groupingBy( score,  () ‐> new TreeMap<>(Comparator.reverseOrder()),  Collectors.toList() ) ) ;
  • 284. #J8Stream @JosePaumard Histogramme des scoresHistogramme des scores • Java Stream GS Collections Rx Java Function< Function<String, Integer>, MutableMap<Integer, MutableList<String>>> buildHistoOnScore =  score ‐> shakespeareWords .select(scrabbleWords::contains) .select(checkBlanks) .aggregateBy( score,  FastList::new,  (list, value) ‐> { list.add(value) ; return list ; } ) ;
  • 285. #J8Stream @JosePaumard Histogramme des scoresHistogramme des scores • Java Stream GS Collections Rx Java Func1<Func1<String, Observable<Integer>>, Observable<TreeMap<Integer, List<String>>>>  buildHistoOnScore = score ‐> Observable.from(() ‐> shakespeareWords.iterator()) .filter(scrabbleWords::contains) .filter(word ‐> checkBlanks.call(word).toBlocking().first()) .collect( () ‐> new TreeMap<Integer,  List<String>>(Comparator.reverseOrder()),  (TreeMap<Integer, List<String>> map, String word) ‐> { Integer key = score.call(word).toBlocking().first() ; List<String> list = map.get(key) ; if (list == null) { list = new ArrayList<String>() ; map.put(key, list) ; } list.add(word) ; }) ;
  • 286. #J8Stream @JosePaumard Meilleurs motsMeilleurs mots • Java Stream GS Collections Rx Java // best key / value pairs List<Entry<Integer, List<String>>> finalList =  buildHistoOnScore.apply(score3).entrySet() .stream() .limit(3) .collect(Collectors.toList()) ;
  • 287. #J8Stream @JosePaumard Meilleurs motsMeilleurs mots • Java Stream GS Collections Rx Java // best key / value pairs MutableList<Entry<Integer, MutableList<String>>> finalList =  new FastList<Map.Entry<Integer,MutableList<String>>>( new TreeSortedMap<Integer, MutableList<String>>( Comparator.reverseOrder(),  buildHistoOnScore.valueOf(score3) ) .entrySet() ) .subList(0, 3) ;
  • 288. #J8Stream @JosePaumard Meilleurs motsMeilleurs mots • Java Stream GS Collections Rx Java // best key / value pairs List<Entry<Integer, List<String>>> finalList2 = buildHistoOnScore.call(score3) .flatMap(map ‐> Observable.from(() ‐> map.entrySet().iterator())) .take(3) .collect( () ‐> new ArrayList<Entry<Integer, List<String>>>(),  (list, entry) ‐> { list.add(entry) ; } ) .toBlocking() .first() ;
  • 289. #J8Stream @JosePaumard Meilleurs motsMeilleurs mots • Java Stream GS Collections Rx Java // best key / value pairs CountDownLatch latch = new CountDownLatch(3) ; buildHistoOnScore.call(score3) .flatMap(map ‐> Observable.from(() ‐> map.entrySet().iterator())) .take(3) .collect( () ‐> new ArrayList<Entry<Integer, List<String>>>(),  (list, entry) ‐> { list.add(entry) ; latch.countDown() ; } ) .forEach(...) ; latch.await() ;
  • 290. #J8Stream @JosePaumard 1er bilan : patterns1er bilan : patterns • Java 8 Stream donne les patterns les plus simples
  • 291. #J8Stream @JosePaumard 1er bilan : patterns1er bilan : patterns • Java 8 Stream donne les patterns les plus simples • Java 8 Stream & GS Collections se ressemblent
  • 292. #J8Stream @JosePaumard 1er bilan : patterns1er bilan : patterns • Java 8 Stream donne les patterns les plus simples • Java 8 Stream & GS Collections se ressemblent • RxJava fait le choix du « tout flatMap » ce qui mène à des patterns inutilement lourds
  • 293. #J8Stream @JosePaumard PerformancesPerformances • Utilisation de JMH • Outil standard de mesure de performances du JDK • Développé dans le cadre de l’Open JDK • Aleksey Shipilev http://shipilev.net/ • https://twitter.com/shipilev http://openjdk.java.net/projects/code-tools/jcstress/ http://openjdk.java.net/projects/code-tools/jmh/ https://www.parleys.com/tutorial/java-microbenchmark-harness-the-lesser-two-evils
  • 294. #J8Stream @JosePaumard PerformancesPerformances • Utilisation de JMH • Outil standard de mesure de performances du JDK • Développé dans le cadre de l’Open JDK • Aleksey Shipilev http://shipilev.net/ • https://twitter.com/shipilev http://openjdk.java.net/projects/code-tools/jcstress/ http://openjdk.java.net/projects/code-tools/jmh/ https://www.parleys.com/tutorial/java-microbenchmark-harness-the-lesser-two-evils Aleksey Shipilëv @shipilev Чувак из ТВ-службы пришёл отключать антенну. Оказался масс-спектрометристом, сцепился языком с тестем: стоят, обсуждают девайсы. #наукоград
  • 295. #J8Stream @JosePaumard JMHJMH • Simple à utiliser <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh‐core</artifactId> <version>1.7</version> </dependency>
  • 296. #J8Stream @JosePaumard JMHJMH • État partagé entre les exécutions @State(Scope.Benchmark) public class ShakespearePlaysScrabble { Set<String> scrabbleWords = null ; Set<String> shakespeareWords = null ; @Setup public void init() { scrabbleWords = Util.readScrabbleWords() ; shakespeareWords = Util.readShakespeareWords() ; } }
  • 297. #J8Stream @JosePaumard JMHJMH • Simple à mettre en œuvre @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) @Warmup(iterations=5) @Measurement(iterations=5) @Fork(3) public List<Entry<Integer, List<String>>> measureAverage() { // implementation to test }
  • 298. #J8Stream @JosePaumard JMHJMH • Utilisation particulière > mvn clean install > java –jar target/benchmark.jar
  • 299. #J8Stream @JosePaumard JMHJMH • 3 façons de mesurer les performances  Temps moyen d’exécution  Nombre d’exécutions par seconde  Échantillonnage (diagramme par quantiles)
  • 300. #J8Stream @JosePaumard PerformancesPerformances • Mesure du temps moyen Benchmark           Mode  Cnt Score   Error Units GSCollections avgt 100   25,392 ± 0,253  ms/op
  • 301. #J8Stream @JosePaumard PerformancesPerformances • Mesure du temps moyen Benchmark           Mode  Cnt Score   Error Units GSCollections avgt 100   25,392 ± 0,253  ms/op NonParallelStreams avgt 100   29,027 ± 0,279  ms/op
  • 302. #J8Stream @JosePaumard PerformancesPerformances • Mesure du temps moyen Benchmark           Mode  Cnt Score   Error Units GSCollections avgt 100   25,392 ± 0,253  ms/op NonParallelStreams avgt 100   29,027 ± 0,279  ms/op RxJava avgt 100  253,788 ± 1,421  ms/op
  • 303. #J8Stream @JosePaumard PerformancesPerformances • Mesure du temps moyen Benchmark           Mode  Cnt Score   Error Units GSCollections avgt 100   25,392 ± 0,253  ms/op NonParallelStreams avgt 100   29,027 ± 0,279  ms/op RxJava avgt 100  253,788 ± 1,421  ms/op ParallelStreams avgt 100    7,624 ± 0,055  ms/op
  • 304. #J8Stream @JosePaumard PerformancesPerformances • Mesure du temps moyen • Attention à la mémoire avec GS Collections Benchmark           Mode  Cnt Score   Error Units GSCollections avgt 100   25,392 ± 0,253  ms/op NonParallelStreams avgt 100   29,027 ± 0,279  ms/op RxJava avgt 100  253,788 ± 1,421  ms/op ParallelStreams avgt 100    7,624 ± 0,055  ms/op
  • 306. #J8Stream @JosePaumard ConclusionConclusion • La programmation fonctionnelle est « à la mode » • Du point de vue performance, les choses ne sont pas si simples • Le choix de l’API Stream : « une dose de fonctionnel » est probablement le bon
  • 307. #J8Stream @JosePaumard ConclusionConclusion • GS Collections : bonne API  Beaucoup de patterns en doublon des Streams  Compatible Java 7 • RxJava : API riche et complexe  Approche différente, patterns complémentaires  Attention aux performances
  • 308. #J8Stream @JosePaumard ConclusionConclusion • Java 8 Stream  Performante, efficace en mémoire  Seule à offrir la parallélisation « gratuite »  Extensible au travers des Spliterator