Aller au contenu principal

Collections et Streams

Progression

#Collections, Streams et parallélisme

Cette partie du cours est ancrée dans des scénarios très concrets : analyser des logs, agréger des statistiques de commandes, traiter un pipeline d’événements. Avant de sortir les Streams, nous revenons sur les structures de base et leurs implications. Pourquoi un ArrayList domine souvent une liste chaînée en pratique ? Dans quels cas LinkedHashMap devient un allié précieux pour préserver l’ordre ? Comment éviter les pièges de ConcurrentHashMap et de CopyOnWriteArrayList lorsqu’on entre dans le domaine de la concurrence ?

Une fois ces choix explicités, nous décortiquons l’API Stream. Les étudiantes et étudiants apprennent à raisonner sur la paresse des flux, à composer les transformations (map, filter, flatMap) et à choisir les collecteurs qui produisent une structure pertinente. Nous détaillons également ce que signifie la parallélisation d’un Stream, quand il est pertinent d’activer parallel() et quels coûts surveiller.

javajava
1var topProduits = commandes.stream()2    .flatMap(c -> c.lignes().stream())3    .collect(groupingBy(LigneCommande::produit, summingInt(LigneCommande::quantite)))4    .entrySet().stream()5    .sorted(Map.Entry.<Produit, Integer>comparingByValue().reversed())6    .limit(10)7    .toList();

#Parallélisme structuré

Au-delà des Streams, Java propose toute une palette pour structurer le parallélisme. Nous passons en revue CompletableFuture avec un atelier qui agrège des appels réseau simulés, puis nous montrons comment StructuredTaskScope améliore la lisibilité du code concurrent en imposant une hiérarchie claire aux tâches. Les virtual threads issus du projet Loom offrent enfin un moyen simple d’augmenter la concurrence d’un service I/O bound sans faire exploser la complexité.

#Exercices

  • Implémentez un pipeline de calcul de statistiques sur des logs JSON massifs.
  • Transformez une API REST bloquante en version Loom.