
FAQ Langage JavaConsultez toutes les FAQ
Nombre d'auteurs : 42, nombre de questions : 297, derni�re mise � jour : 19 septembre 2017 Ajouter une question
Cette FAQ a �t� r�alis�e � partir des questions fr�quemment pos�es sur le forum Java de http://java.developpez.com ainsi que l'exp�rience personnelle des auteurs.
Nous tenons � souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne pr�tend pas non plus �tre compl�te. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant r�dacteur, lisez ceci.
Sur ce, nous vous souhaitons une bonne lecture.
- Qu'est-ce qu'un stream ?
- Est-il possible de r�utiliser un flux ?
- Quels sont les types de flux ?
- Comment cr�er un stream ?
- Qu'est-ce qu'une op�ration � stateless � ou � stateful � ?
- Qu'est-ce qu'une op�ration � short-circuiting � ?
- Comment convertir un flux d'un type en un flux d'un autre type ?
- Comment convertir un flux en collection ?
- Comment convertir un flux en tableau ?
Un stream (data stream ou flux de donn�es ou flot de donn�es) est un concept introduit depuis le JDK�8, et qui repr�sente un ensemble de donn�es. Les flux, en eux-m�mes, ne d�finissent pas une nouvelle mani�re de stocker des donn�es�; ils d�finissent au contraire une nouvelle mani�re d'appliquer des op�rations sur un ensemble de donn�es qui s'apparente, par exemple, � ce qui peut �tre fait en SQL. Ainsi, il est possible de traiter un ensemble de mani�re s�quentielle ou parall�le, ou m�me de le diviser en sous-flux. On peut lui appliquer des filtres, des conversions, des r�ductions, des tris, des traitements ou des op�rations arithm�tiques ou statistiques. De plus, il est possible de convertir un flux en collection ou tableau. La source m�me du flux peut �tre une collection, un tableau ou encore une source de donn�es dynamiques.
Attention�: il ne faut pas confondre les flux sur les donn�es (streams ou data streams) et les flux d�entr�e sortie (I/O streams) qui sont bien plus anciens dans la JVM.
Un stream permet donc de manipuler simplement un flux de donn�es quelconque. L'utilisation d'un flux se compose de trois �tapes�:
- La cr�ation du stream � partir d'une source de donn�es (tableau, Collection, fonction de g�n�ration, etc.)�;
- Z�ro, une ou plusieurs d�clarations d'op�rations interm�diaires, qui permettent de modifier le comportement du flux de diff�rentes mani�res. Chacune de ces op�rations retourne un nouveau flux, mais ces derniers sont cr��s de mani�re lazy (paresseuse)�: aucun traitement n'est effectu� lors de leur d�claration.
- Un appel de l'op�ration terminale qui va fournir un r�sultat. C'est elle qui va d�clencher le parcours des donn�es et ex�cuter les diff�rentes op�rations interm�diaires.
Remarque : la manipulation du stream n'a aucun impact sur la source de donn�es, mais uniquement sur le r�sultat du stream.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 | IntStream.range(0, 10000) // 1. Cr�ation d'un Stream d'int allant de 0 � 10�000. .filter(i -> i%2==0 && i%3==0 && i%5==0) // 2. Op�ration interm�diaire�: on n'accepte que les valeurs divisibles � la fois par 2, 3 et 5. .forEach(System.out::println); // 3. Op�ration finale�: on boucle sur les valeurs, pour les afficher avec System.out.println(). |
Non, il n'est pas possible de r�utiliser un flux. Les streams sont con�us pour �tre utilis�s via un cha�nage de m�thodes, et ils ne peuvent �tre utilis�s qu'une seule fois�: au moment auquel l'op�ration terminale est invoqu�e. Cependant, les op�rations terminales iterator() et spliterator() �chappent en partie � cette r�gle en diff�rant l�ex�cution des op�rations interm�diaires jusqu'au moment de la manipulation des it�rateurs retourn�s par ces m�thodes.
Il existe quatre types de flux�:
- Stream - repr�sente les flux sur des objets�;
- IntStream - repr�sente un flux sp�cialis� d'int�;
- LongStream - repr�sente un flux sp�cialis� de long�;
- DoubleStream - repr�sente un flux sp�cialis� de double.
Il est possible de passer d'un type de flux � un autre en invoquant des op�rations interm�diaires de conversion.
Il existe plusieurs mani�res de cr�er un stream�: on peut utiliser une source de donn�es pr�existante, ou m�me une m�thode qui nous g�n�rera les donn�es au fur et � mesure du parcours du flux (utile pour des flux ��infinis��).
Les streams basent leur fonctionnement sur des instances de la classe Spliterator, une sorte de super-it�rateur qui peut se d�couper en deux et conserve certaines caract�ristiques de la source de donn�es afin d'optimiser le traitement. En th�orie, il faudrait passer par les m�thodes statiques de la classe StreamSupport pour cr�er un Stream � partir d'un Spliterator. Heureusement, l'API standard nous offre plusieurs mani�res d'obtenir un flux, si bien qu'il sera rare d'avoir � utiliser le Spliterator.
En voici une liste non exhaustive�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | // Stream vide�: Stream.empty(); // Stream infini g�n�r� � partir de Math.random()�: Stream.generate(Math::random); // Stream � partir d'une liste de valeur Stream.of("a", "b", "c"); // Stream g�n�r� dynamiquement, repr�sentant les valeurs de 0 � 100 (compris ou pas) IntStream.rangeClosed(0, 100); IntStream.range(0, 100); // Stream repr�sentant la concat�nation de deux Streams�: IntStream.concat( IntStream.range(0, 100), IntStream.of(200, 300, 400, 500)); // Stream g�n�r� dynamiquement, repr�sentant les valeurs num�riques via un incr�ment de 0.5�: DoubleStream.iterate(0.0, n -> n + 0.5); // Stream g�n�r� � partir du contenu d'un tableau�: String[] array = { "a", "b", "c" }; Arrays.stream(array); // Stream g�n�r� � partir du contenu d'une collection (List, Set, ...)�: Collection<String> collection = Arrays.asList("a", "b", "c"); collection.stream(); // M�me chose, mais avec un Stream parall�le�: collection.parallelStream(); try (BufferedReader reader�: Files.newBufferedReader(Paths.get("in.txt"))) { // Stream obtenu � partir des lignes du fichier�: reader.lines(); } |
L'utilisation la plus fr�quente consiste � invoquer la m�thode stream() de l'API de Collection, qui permet d'obtenir un Stream se basant sur le contenu de la collection en question.
Une op�ration stateless (sans �tat) est un type d�op�rations interm�diaires qui ne g�re aucun �tat pendant le traitement du flux, ce qui permet de parall�liser les traitements sans trop de surco�ts. Ces op�rations se basent uniquement sur l'�l�ment courant du flux, ind�pendamment des autres �l�ments.
Cependant, il existe quelques op�rations interm�diaires dites stateful (litt�ralement ��pleine d��tat��) qui doivent g�rer un �tat pour effectuer correctement leur traitement (par exemple�: les op�rations skip(), limit(), distinct() et sorted()). Ces op�rations peuvent devenir tr�s co�teuses si on manipule un flux de donn�es � la fois ordonn� et en parall�le. Dans ce cas-l�, il peut �tre pr�f�rable d'utiliser un traitement s�quentiel (via l�op�ration sequential()) ou d'ignorer l'ordre des �l�ments (via l�op�ration unordered()), selon ce qui s'adapte le mieux � votre besoin.
Une op�ration short-circuiting (court-circuitante) est une op�ration interm�diaire qui ne va pas obligatoirement traiter tous les �l�ments du flux. Par exemple, l�op�ration limit() va seulement traiter N �l�ments du flux. L�op�ration findFirst() va, quant � elle, arr�ter d�s qu'elle trouvera le premier �l�ment correspondant ; ce qui permet d'utiliser des streams infinis, sans boucler ind�finiment.
Il est possible de convertir un flux d'un type A en un flux d'un type B en invoquant une des variantes de l�op�ration map() de ce flux. Cette op�ration est interm�diaire.
- map() - permet de convertir un Stream<T> en Stream<V>�;
- mapToDouble() - permet de convertir un Stream<T> en DoubleStream�;
- mapToInt() - permet de convertir un Stream<T> en IntStream�;
- mapToLong() - permet de convertir un Stream<T> en LongStream.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 | Stream<Client> fluxDeClient = [...] Stream<NumeroDeTelephone> fluxDeClient.map(client -> client.getNumeroDeTelephone()); IntStream fluxDAge = fluxDeClient.mapToInt(client -> client.getAge()); |
De plus, les flux de literals permettent d'obtenir des flux objet du type wrapper �quivalent en invoquant l�op�ration boxed() de ces flux. Cette op�ration est interm�diaire.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 | IntStream fluxLiteral = IntStream.range(0, 10); Stream<Integer> fluxWrapper = fluxLiteral.boxed(); |
Il est possible de convertir un flux en un type de stockage arbitraire en invoquant l�op�ration collect() de ce flux et en passant � cette op�ration une instance de la classe java.util.stream.Collector<T,A,R>. Cette op�ration est terminale.
Ici�:
- T est le type des �l�ments du flux�;
- A est un type interm�diaire g�n�ralement laiss� aux soins de l�impl�mentation de l�op�ration�;
- R est le type r�sultat de l�op�ration (qui peut �tre autre chose qu'une collection).
L'API stream fournit de base la classe utilitaire java.util.stream.Collectors qui propose plusieurs m�thodes qui fournissent des collecteurs pr�ts � l'emploi pour convertir un flux en collections�:
- toCollection() - permet la cr�ation d'une Collection<V> (collection arbitraire) � partir du flux de type Stream<T>�;
- toConcurrentMap() - permet la cr�ation d'une ConcurrentMap<U, V> (dictionnaire disposant de m�thodes synchronis�es) � partir du flux de type Stream<T>�;
- toList() - permet la cr�ation d'une List<T> (liste) � partir du flux de type Stream<T>�;
- toMap() - permet la cr�ation d'une Map<U, V> (dictionnaire) � partir du flux de type Stream<T>�;
- toSet() - permet la cr�ation d'un Set<T> (ensemble) � partir du flux de type Stream<T>.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | List<Integer> listeDEntiers = IntStream.range(0, 10) .boxed() .collect(Collectors.toList()); [...] Stream<Client> fluxDeClients = [...] // Le premier param�tre du g�n�rateur sert � g�n�rer les cl�s de l'association�; tandis que le second param�tre sert � g�n�rer la valeur associ�e � cette cl�. // Ici, l'id du client sert de cl� dans l'association. // La valeur associ�e � cette cl� est le client lui-m�me. Map<Integer, Client> associationDeClients = fluxDeClients.collect(Collectors.toMap(client -> client.getId(), client -> client)); // Ou�: Map<Integer, Client> associationDeClients = fluxDeClients.collect(Collectors.toMap(client -> client.getId(), Functions.identity())); |
Il est possible de convertir un flux en un tableau en invoquant une des variantes de l�op�ration toArray() de ce flux. Cette op�ration est terminale.
toArray()
Cette version de la m�thode, qui n'a pas d'argument, permet de g�n�rer un tableau d'objets (Object[]).
Par exemple�:
Code Java : | S�lectionner tout |
1 2 | Stream<Client> fluxDeClients = [...] Object[] tableauDeClients = fluxDeClients.toArray(); |
toArray(generator)
Cette seconde version de la m�thode prend en param�tre un g�n�rateur de tableaux qui permet d'instancier un tableau � la taille requise. Elle renvoie un tableau du m�me type que les objets contenus dans le flux. Le g�n�rateur est une fonction qui prend un entier, la taille du tableau, en param�tre et renvoie un tableau de la taille et du type voulu. Ce g�n�rateur peut �tre, tout simplement, une r�f�rence de m�thode vers le constructeur de tableaux du type appropri�.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 | Stream<Client> fluxDeClients = [...] Client[] tableauDeClients = fluxDeClients.toArray(taille -> new Client[taille]); // Ou on donne une r�f�rence au constructeur de tableaux. Client[] tableauDeClients = fluxDeClients.toArray(Client[]::new); |
Proposer une nouvelle r�ponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plut�t sur le forum de la rubrique pour �aLes sources pr�sent�es sur cette page sont libres de droits et vous pouvez les utiliser � votre convenance. Par contre, la page de pr�sentation constitue une �uvre intellectuelle prot�g�e par les droits d'auteur. Copyright � 2025 Developpez Developpez LLC. Tous droits r�serv�s Developpez LLC. Aucune reproduction, m�me partielle, ne peut �tre faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'� trois ans de prison et jusqu'� 300 000 � de dommages et int�r�ts.