0. Exemple de classe et de données
class Etudiant {
private int echecs;
private String nom;
private String profChinois;
private String profPrincipal;
public Etudiant(int echecs, String nom, String profChinois, String profPrincipal) {
this.echecs = echecs;
this.nom = nom;
this.profChinois = profChinois;
this.profPrincipal = profPrincipal;
}
public int getEchecs() { return echecs; }
public String getNom() { return nom; }
public String getProfChinois() { return profChinois; }
public String getProfPrincipal() { return profPrincipal; }
public void setEchecs(int echecs) { this.echecs = echecs; }
public void setNom(String nom) { this.nom = nom; }
public void setProfChinois(String profChinois) { this.profChinois = profChinois; }
public void setProfPrincipal(String profPrincipal) { this.profPrincipal = profPrincipal; }
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Etudiant)) return false;
Etudiant autre = (Etudiant) obj;
return echecs == autre.echecs &&
Objects.equals(nom, autre.nom) &&
Objects.equals(profChinois, autre.profChinois) &&
Objects.equals(profPrincipal, autre.profPrincipal);
}
@Override
public int hashCode() {
return Objects.hash(echecs, nom, profChinois, profPrincipal);
}
@Override
public String toString() {
return "Etudiant{echecs=" + echecs + ", nom='" + nom + "', profChinois='" + profChinois + "', profPrincipal='" + profPrincipal + "'}";
}
}
List<Etudiant> listeEtudiants = new ArrayList<>();
listeEtudiants.add(new Etudiant(5, "zhangsan", "prof1", "prof2"));
listeEtudiants.add(new Etudiant(1, "lisi", "prof1", "prof2"));
listeEtudiants.add(new Etudiant(3, "wangwu", "prof2", "prof1"));
listeEtudiants.add(new Etudiant(10, "zhaoliu", "prof2", "prof1"));
listeEtudiants.add(new Etudiant(10, "zhaoqi", "prof2", "prof1"));
1. Opérations intermédiaires
filter : Filtre les éléments en fonction d'un prédicat défini par une expression lambda.
listeEtudiants.stream()
.filter(etudiant -> etudiant.getEchecs() >= 3)
.forEach(System.out::println);
map : Transforme chaque élément en appliquant une fonction de mapping.
listeEtudiants.stream()
.map(etudiant -> etudiant.getNom().length())
.forEach(System.out::println);
Il est courant d'utiliser map pour modifier les éléments, par exemple en ajoutant une propriété :
listeEtudiants.stream()
.map(etudiant -> {
if (etudiant.getEchecs() == 0) {
etudiant.setEstExcellent(true);
} else {
etudiant.setEstExcellent(false);
}
return etudiant;
})
.map(etudiant -> etudiant.isEstExcellent())
.forEach(System.out::println);
sorted : Trie les éléments selon un comparateur fourni.
listeEtudiants.stream()
.map(Etudiant::getNom)
.map(String::length)
.sorted((a, b) -> b - a)
.forEach(System.out::println);
limit : Resterint le flux aux n premiers éléments.
listeEtudiants.stream()
.map(Etudiant::getNom)
.map(String::length)
.sorted((a, b) -> b - a)
.limit(3)
.forEach(System.out::println);
skip : Ignore les n premiers éléments du flux.
listeEtudiants.stream()
.map(Etudiant::getNom)
.map(String::length)
.sorted((a, b) -> b - a)
.skip(3)
.forEach(System.out::println);
distinct : Élimine les doublons du flux.
listeEtudiants.stream()
.map(Etudiant::getNom)
.map(String::length)
.sorted((a, b) -> b - a)
.distinct()
.forEach(System.out::println);
2. Opérations terminales
forEach : Applique une action à chaque élément, ne retourne pas de flux.
peek : Similaire à forEach mais utilisé en milieu de pipeline, retourne le flux.
Optional<Integer> resultat = listeEtudiants.stream()
.map(etudiant -> etudiant.getNom().length())
.sorted((a, b) -> b - a)
.distinct()
.peek(System.out::println)
.reduce((somme, val) -> somme + val);
System.out.println(resultat.get());
reduce : Agrège les éléments en une seule valeur.
collect : Transforme le flux en une collection souhaitée.
Map<String, List<Etudiant>> regroupement = listeEtudiants.stream()
.filter(etudiant -> etudiant.getEchecs() >= 2)
.collect(Collectors.groupingBy(Etudiant::getProfChinois));
System.out.println(regroupement);
List<Etudiant> listeFiltree = listeEtudiants.stream()
.filter(etudiant -> etudiant.getEchecs() >= 2)
.collect(Collectors.toList());
System.out.println(listeFiltree);
allMatch : Vérifie si tous les éléments satifsont un prédicat.
boolean tousAdmis = listeEtudiants.stream()
.allMatch(etudiant -> etudiant.getEchecs() == 0);
System.out.println(tousAdmis);
anyMatch : Vérifie si au moins un élément satisfait un prédicat.
boolean auMoinsUnAdmis = listeEtudiants.stream()
.anyMatch(etudiant -> etudiant.getEchecs() == 0);
System.out.println(auMoinsUnAdmis);
noneMatch : Vérifie si aucun élément ne satisfait un prédicat.
boolean aucunAdmis = listeEtudiants.stream()
.noneMatch(etudiant -> etudiant.getEchecs() == 0);
System.out.println(aucunAdmis);
findFirst : Récupère le premier élément du flux.
Optional<Etudiant> premier = listeEtudiants.stream().findFirst();
System.out.println(premier.get());
findAny : Récupère un élément arbitraire ; identique à findFirst dans un flux séquentiel, utile en parallèle.
Optional<Etudiant> nimporteQuel = listeEtudiants.parallelStream().findAny();
System.out.println(nimporteQuel.get());
count : Retourne le nombre d'éléments dans le flux.
long nombre = listeEtudiants.stream()
.map(Etudiant::getEchecs)
.distinct()
.peek(System.out::println)
.count();
System.out.println(nombre);
max/min : Retourne le maximum ou le minimum selon un comparateur.
Optional<Integer> maximum = listeEtudiants.stream()
.map(Etudiant::getEchecs)
.distinct()
.max(Integer::compareTo);
System.out.println(maximum.get());
Optional<Integer> minimum = listeEtudiants.stream()
.map(Etudiant::getEchecs)
.distinct()
.min(Integer::compareTo);
System.out.println(minimum.get());
parallel/parallelStream : Convertit le flux en mode parallèle pour accélérer le traitement (attention à la concurrence).
Optional<Etudiant> parallele = listeEtudiants.parallelStream().findAny();
System.out.println(parallele.get());