CodeGym /Cours /JAVA 25 SELF /Introduction à l’API Stream : pourquoi les flux sont...

Introduction à l’API Stream : pourquoi les flux sont utiles

JAVA 25 SELF
Niveau 30 , Leçon 0
Disponible

1. Problème de l’approche impérative

Commençons par un exercice classique. Supposons que nous ayons une liste d’utilisateurs :

List<User> users = ...; // déjà rempli

Supposons qu’il nous faille obtenir la liste des noms de tous les utilisateurs majeurs (à partir de 18 ans). Comment faisions‑nous avant ?

List<String> names = new ArrayList<>();
for (User user : users) {
    if (user.getAge() >= 18) {
        names.add(user.getName());
    }
}

À première vue, tout est simple, mais remarquez les étapes « techniques » : déclarer une nouvelle liste pour le résultat, parcourir tous les éléments, vérifier la condition, ajouter le résultat.

Si la tâche se complique — par exemple, obtenir la liste triée alphabétiquement des e‑mails uniques de tous les utilisateurs dont les noms commencent par la lettre « A » — le code enfle rapidement : filtrage, extraction de champs, suppression des doublons, tri, éventuellement normalisation du format de l’e‑mail, etc. Au final, au lieu d’une logique courte et claire, vous vous retrouvez avec une montagne de boilerplate, difficile à lire et à maintenir.

Les inconvénients de cette approche, en deux mots : beaucoup de code répétitif, une forte probabilité d’erreur (oublier le tri ou mal gérer les doublons), et une composition d’opérations compliquée. C’est ce qu’on appelle le style impératif : vous décrivez pas à pas à l’ordinateur comment effectuer la tâche, et non ce que vous voulez obtenir.

2. API Stream — style déclaratif

Avec Java 8 est arrivée l’API Stream — un outil qui permet de travailler avec les collections dans le style « ce qu’il faut faire » plutôt que « comment exactement le faire ». Cette approche est dite déclarative.

Qu’est-ce qu’un Stream, au juste ?
Ce n’est pas une collection séparée, mais plutôt un flux de données : une séquence d’éléments qui passent par une chaîne d’opérations — filtrage, transformation, tri, collecte du résultat, etc. Le flux ne stocke rien, il « fait passer » les données à travers un pipeline. Les opérations se combinent presque comme des briques LEGO : on compose une chaîne et on lance.

Exemple :

List<String> names = users.stream()                // on crée un flux à partir de la liste d'utilisateurs
    .filter(u -> u.getAge() >= 18)                 // ne garder que ceux qui ont déjà 18 ans 
    .map(User::getName)                            // transformer User → String (prendre le nom)
    .collect(Collectors.toList());                 // collecter le résultat dans une liste

Et voilà — en une seule ligne, nous avons décrit toute la tâche : « prends les utilisateurs, filtre par âge, récupère les noms, collecte dans une liste ». Pas besoin d’écrire des boucles à la main, de créer des variables temporaires ni de veiller à n’oublier aucune étape.

Stream API fonctionne comme un pipeline industriel : vous définissez les étapes de traitement et les données les traversent d’elles‑mêmes. C’est élégant, compact et bien plus lisible.

3. Avantages de l’API Stream

  • Concision et lisibilité. Comparez les deux approches — impérative et déclarative — sur une même tâche. On voit immédiatement laquelle est la plus facile à lire et à maintenir.
  • Composition d’opérations aisée. Les opérations se « chaînent » facilement : filter, map, sorted, collect — le tout dans une seule séquence cohérente.
  • Moins d’erreurs. Stream API débarrasse de la routine : pas besoin de gérer manuellement les collections intermédiaires et les boucles — moins de risques d’oublier une étape ou de faire une erreur d’index.
  • Possibilité de parallélisme. Il est facile de répartir le traitement sur plusieurs cœurs en appelant simplement parallelStream() au lieu de stream(). Les détails — plus loin.
  • Style de programmation moderne. Les idées de la programmation fonctionnelle (composition de fonctions, absence de boucles explicites) augmentent l’expressivité et sont appréciées sur le marché.

Bref historique de l’API Stream

Stream API est apparue avec Java 8 (2014) et a marqué un saut qualitatif pour le langage. Auparavant, toute opération non triviale sur des collections exigeait beaucoup de code auxiliaire, alors que d’autres plateformes proposaient déjà des approches déclaratives (map, filter, reduce, etc.).

Depuis, l’API Stream est la norme de facto pour traiter des collections en Java. Si vous voulez écrire du code Java moderne — on ne peut pas s’en passer.

4. Cas d’utilisation de l’API Stream

  • Filtrage : ne sélectionner que les éléments nécessaires (par exemple, tous les utilisateurs de plus de 18 ans).
  • Transformation : extraire un champ ou créer un nouvel objet (par exemple, la liste des noms d’utilisateurs).
  • Agrégation : calculer une somme, une moyenne, un compte, un maximum/minimum.
  • Tri : ordonner les éléments selon le critère souhaité.
  • Regroupement : répartir les éléments par catégories.
  • Collecte du résultat : rassembler dans une liste, un ensemble, une map, une chaîne, etc.

Exemples :

  • Obtenir la liste des e‑mails de tous les utilisateurs dont le nom commence par la lettre « A ».
  • Calculer l’âge moyen des utilisateurs.
  • Trouver le premier utilisateur avec un e‑mail donné.
  • Rassembler toutes les villes de résidence uniques dans un seul ensemble.

5. Subtilités utiles

Comment fonctionne un flux

[User1] --\
[User2] ---|--> [ filter ] --> [ map ] --> [ collect ] --> List<String>
[User3] --/

1. filter — ne laisse passer que les utilisateurs qui satisfont la condition.
2. map — transforme un utilisateur en, par exemple, e‑mail.
3. collect — collecte les e‑mails dans la collection souhaitée.

Syntaxe : comment créer un flux

  • Depuis une collection : list.stream() — flux des éléments de la collection.
  • Depuis un tableau : Arrays.stream(array)
  • Depuis des valeurs distinctes : Stream.of("a", "b", "c")

6. Erreurs courantes lors du passage à l’API Stream

Erreur n° 1 : tenter de modifier la collection à l’intérieur d’un flux. Stream API n’est pas conçue pour modifier la collection d’origine (par exemple, éviter de faire list.remove() dans le corps d’un forEach). Pour les suppressions, utilisez par exemple removeIf sur la collection, avant ou après le traitement.

Erreur n° 2 : confusion entre collection et flux. Un flux n’est pas une collection ! Le flux « parcourt » les éléments une seule fois, puis se ferme. Si vous devez traiter à nouveau les données, créez un nouveau stream().

Erreur n° 3 : chaînes trop complexes. N’en faites pas un « monstre » de dix opérations. Si la chaîne devient longue, scindez‑la en plusieurs étapes avec des variables intermédiaires pour améliorer la lisibilité et faciliter le débogage.

1
Mission
JAVA 25 SELF, niveau 30, leçon 0
Bloqué
Suivi de la progression dans le jeu 🎮
Suivi de la progression dans le jeu 🎮
1
Mission
JAVA 25 SELF, niveau 30, leçon 0
Bloqué
Classification des produits pour une boutique en ligne 🏷️
Classification des produits pour une boutique en ligne 🏷️
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION