Les Streams Java 8
Des boucles java 7 aux Streams Java 8, par lexemple
Exemple dun filtre
Soit une liste de clients
List<Client> clients = [Link](
new Client("Jean", "Dupont", 41),
new Client("Yves", "Durant", 36),
new Client("Yvan", "Lemeux", 15)
);
Besoin : afficher les clients dont le nom commence par la lettre D
Client{nom='Dupont', prenom='Jean', age=41}
Client{nom='Durant', prenom='Yves', age=36}
En Java 7
for (Client client : clients) {
if ([Link]().startsWith("D")) {
[Link](client);
}
}
En Java 8
[Link]()
.filter(c -> [Link]().startsWith("D"))
.forEach([Link]::println);
Stream
Nouveau concept introduit dans Java 8
Permet de traiter efficacement de grands comme de petits volumes de donnes
Un Stream nest pas une collection
Ne stocke pas de donnes
Ne viens pas polluer lAPI Collection
Stream<Client> stream = [Link]();
Techniquement,
une interface :
public interface Stream<T> extends BaseStream<T, Stream<T>> {
Et des mthodes : filter, map, reduce, sorted, count, collect, forEach
Oprations intermdiaires et terminales
Un stream est un pipeline doprations
0 N opration(s) intermdiaire(s)
Retourne toujours un Stream (chanage possible)
Dclaratif : leur traitement nest ralis que lors de lappel de lopration terminale
Stateful ou staless
Exemple : filter, map
1 opration terminale
Optimise et excute les oprations intermdiaires
Consomme le Stream
Exemple : count, forEach
Map Reduce
Besoin : Avec la mme liste de clients, on souhaite calculer lge moyen des clients majeurs
En Java 7
int nbClient = 0, ageSum = 0;
for (Client client : clients) {
if ([Link]() >= 18) {
nbClient++;
ageSum += [Link]();
}
}
Double average = (double) ageSum / nbClient;
[Link](average);
En Java 8
OptionalDouble average = [Link]()
.filter(c -> [Link]() >= 18)
.mapToInt(Client::getAge)
.average();
[Link]([Link]());
Prdicat
Fonction
Filtre
getAge() >= 18
Map
getAge()
Opration
terminale
Source
Jean, Yves, Yvan
Jean, Yves
41, 36
average
38.5
Recherche
Besoin : afficher le nom du 1er client majeur de la liste prcdente
En Java 7
String nom = null;
for (Client client : clients) {
if ([Link]() >= 18) {
nom = [Link]();
break;
}
}
String msg = nom != null
? nom : "aucun rsultat";
[Link](msg);
En Java 8
String nom = [Link]()
.filter(c -> [Link]() >= 18)
.findFirst()
.map(Client::getNom)
.orElse("aucun rsultat");
[Link](nom);
// Stream<Client>
// Optional<Client>
// Optional<String>
Optional : conteneur pour une valeur qui
peut tre null
Rduction simple
Besoin : rechercher le client le plus g
En Java 7
Client doyen = null;
for (Client client : clients) {
if (doyen == null) {
doyen = client;
} else {
doyen= [Link]() > [Link]()
? doyen : client;
}
}
if (doyen!=null) [Link](doyen);
En Java 8
[Link]()
.reduce((c1, c2) -> [Link]() > [Link]()
? c1 : c2)
.ifPresent([Link]::println);
Une opration de rduction combine tous les
lments dun stream en un seul rsultat
Lopration average() du IntStream est une
rduction prte lemploi
Collecte
Besoin : rcuprer une liste contenant le nom des clients
En Java 7
List<String> noms = new ArrayList<>();
for (Client client : clients) {
[Link]([Link]());
}
En Java 8
List<String> noms = [Link]()
.map(Client::getNom)
.collect([Link]());
La mthode collect est une rduction mutable
Elle accumule les lments dun stream dans un container
La classe Collectors propose des implmentations prtes lemploi de linterface Collector :
toList, toSet, toCollection, toMap
Regroupement
Besoin : regrouper les clients par la 1ire lettre de leur nom
En Java 7
Map<Character, List<Client>>
map = new HashMap<>();
for (Client client : clients) {
char initiale = [Link]().charAt(0);
List<Client> liste = [Link](initiale);
if (liste == null) {
liste = new ArrayList<>();
[Link](initiale, liste);
}
[Link](client);
}
En Java 8
Map<Character, List<Client>> map = [Link]()
.collect([Link](
c -> [Link]().charAt(0)));
Pour aller plus loin
Paralllisation de stream avec la mthode parallelStream()
Rle du Spliterator dans la construction dun Stream
Changement des caractristiques dun Stream en fonction des oprations
Diffrences entre les Stream stateful et stateless
Calculs en une passe avec IntSummaryStatistics et DoubleSummaryStatistics
Streams spcialiss pour les numriques: IntStream, LongStream et DoubleStream
Les Streams infinis et les oprations stoppantes
Les Streams Builder
La mise plat de Streams avec flatMap
Le debuggage de Streams avec peek
Et de nombreuses autres oprations : allMatch, anyMatch, noneMatch, count,
sorted, sum, concat, findAny, limit, skip, min, max
Rfrences
Universit de 3h sur le thme de Java 8, de lAPI Stream et des Collectors
Java 8 Streams cheat sheet by RebelLabs
API Stream Une nouvelle faon de grer les Collections en Java 8