Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Apprendre API de Flux en Java | Fonctionnalités et Techniques Avancées de Java
Structures de Données Java

bookAPI de Flux en Java

Il existe différentes manières de traiter les données en Java – boucles, méthodes et divers algorithmes. Cependant, avec Java 8, un outil très puissant a été introduit : l’API Stream.

En termes simples, l’API Stream permet de travailler rapidement et facilement avec un flux d’informations. Dans notre cas, ce flux d’informations est représenté par des collections. L’API Stream repose sur certains concepts. Voici les principaux.

Concepts principaux

  • Stream : représente une séquence d’éléments de données pouvant être traités ;

  • Opérations intermédiaires : opérations qui créent un nouveau flux après leur exécution. Exemples : filter, map, distinct, sorted ;

  • Opérations terminales : opérations qui terminent le traitement du flux et retournent un résultat. Exemples : collect, forEach, count, reduce ;

  • Streams parallèles : permettent le traitement parallèle des données. Les méthodes parallel() et parallelStream() sont utilisées pour créer des flux parallèles.

Assez parlé de théorie, passons à la pratique !

La déclaration d'un flux se fait en utilisant une méthode sur la collection que vous souhaitez convertir en flux :

Main.java

Main.java

copy
12
List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream();

Avec la méthode stream(), un flux de chaînes de caractères est obtenu. Cependant, pour commencer à travailler avec le flux, il est nécessaire de comprendre ce que sont les expressions lambda, car les méthodes de flux fonctionnent principalement avec celles-ci.

Expressions Lambda

Les expressions lambda ont été introduites dans Java 8 et représentent une forme simplifiée de création de fonctions anonymes en Java. Les fonctions anonymes n'ont pas été abordées auparavant car elles n'étaient pas particulièrement nécessaires, mais nous allons maintenant les découvrir à travers les expressions lambda.

Syntaxe d'une expression lambda :

La syntaxe générale des expressions lambda en Java est la suivante :

Example.java

Example.java

copy
123
(parameters) -> expression // or (parameters) -> { statements; }
  • Paramètres : il s'agit d'une liste de paramètres qui peut être vide ou contenir un ou plusieurs paramètres ;

  • Flèche : représentée par le symbole ->, qui sépare les paramètres du corps de l'expression lambda ;

  • Expression ou instructions : il s'agit du corps de la fonction, contenant une expression ou un bloc d'instructions.

Voici un exemple d'expression lambda représentant une fonction simple qui additionne deux nombres :

Example.java

Example.java

copy
12345678910
// Traditional way MathOperation addition = new MathOperation() { @Override public int operate(int a, int b) { return a + b; } }; // Using a lambda expression MathOperation addition = (int a, int b) -> a + b;

Examinons de plus près ce qui se passe exactement dans le code ci-dessus et comment nous utilisons les expressions lambda :

Main.java

Main.java

copy
1234567891011121314
package com.example; // Functional interface with a single abstract method interface MyMathOperation { int operate(int a, int b); } public class Main { public static void main(String[] args) { // Using a lambda expression to implement the interface MyMathOperation addition = (a, b) -> a + b; System.out.println("Sum: " + addition.operate(5, 3)); } }

Dans le code ci-dessus :

Création d'une interface fonctionnelle MyMathOperation avec une seule méthode abstraite operate.

Utilisation d'une expression lambda pour implémenter cette méthode, réalisant l'addition de deux nombres.

Affichage du résultat de l'addition.

Il est compréhensible que cela puisse être difficile à saisir pour le moment, mais revenons à l'API Stream, où les expressions lambda sont fréquemment utilisées, et essayons de comprendre comment les utiliser en pratique.

Comme vous vous en souvenez, précédemment, nous avons créé un flux de chaînes de caractères à partir d'une liste de chaînes. Utilisons maintenant les méthodes de flux pour transformer chaque chaîne de ce flux en majuscules :

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream(); stream.map(e -> e.toUpperCase()).toList(); } }

Dans le code ci-dessus, une expression lambda et deux méthodes ont été utilisées : map() et toList(). Si la fonction de la méthode toList() est évidente, la méthode map() modifie chaque élément du flux selon l'expression lambda fournie.

Examinons de plus près le fonctionnement de l'expression lambda dans ce contexte :

La méthode map() applique la méthode toUpperCase() à chaque élément du flux. L’élément de ce flux a été défini comme e et, à l’aide de l’expression lambda, le programme a été instruit d’appliquer cette méthode à chaque élément.

Cependant, ce n’est pas encore terminé car une opération intermédiaire a été appliquée. Cela signifie que les opérations sur le flux ne sont pas encore achevées. Pour finaliser le traitement du flux, il est nécessaire d’appliquer une opération terminale, qui terminera les opérations sur le flux et retournera une valeur spécifique. Par exemple, la méthode toList() peut être utilisée, et le flux modifié sera converti en liste.

Par exemple :

Main.java

Main.java

copy
1234567891011121314
package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream(); List<String> list = stream.map(e -> e.toUpperCase()).toList(); System.out.println(list); } }

Examinons de plus près les opérations intermédiaires possibles dans le flux.

Opérations intermédiaires

La méthode map() — vous connaissez déjà cette méthode ; elle effectue les opérations spécifiées par l'expression lambda sur chaque élément du flux.

Par exemple, utilisons la méthode substring() sur chaque élément d'un flux de chaînes de caractères :

Main.java

Main.java

copy
123456789101112131415
package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); Stream<String> stream = strings.stream(); List<String> list = stream.map(e -> e.substring(1, 4)).toList(); System.out.println("Modified list: " + list); } }

La méthode filter() prend une expression lambda avec une condition selon laquelle le flux sera filtré. Autrement dit, tous les éléments qui remplissent la condition vont rester dans le flux, et les éléments qui ne remplissent pas la condition seront supprimés du flux. Modifions le flux pour ne conserver que les éléments dont la longueur est supérieure à 5 :

Main.java

Main.java

copy
12345678910111213141516
package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); Stream<String> stream = strings.stream(); stream = stream.filter(e -> e.length() > 5); List<String> list = stream.map(e -> e.substring(1, 4)).toList(); System.out.println("Modified list: " + list); } }

En utilisant la méthode filter(), la chaîne de caractères "with" est supprimée du flux car ce mot contient moins de 5 caractères.

Il est également possible d'utiliser plusieurs opérations intermédiaires consécutivement.

Par exemple, le code ci-dessus peut être légèrement simplifié :

Main.java

Main.java

copy
12345678910111213141516
package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); List<String> list = strings.stream() .filter(e -> e.length() > 5) .map(e -> e.substring(1, 4)) .toList(); System.out.println("Modified list: " + list); } }

Lors de l'enchaînement de plusieurs méthodes de flux, il est recommandé de placer chaque méthode sur une nouvelle ligne afin d'améliorer considérablement la lisibilité du code.

La méthode flatMap() transforme chaque élément d'un flux en un nouveau flux et combine les résultats en un seul flux. En d'autres termes, avec cette méthode, il est possible de diviser le flux en plusieurs flux, puis ils seront fusionnés en un seul flux. Par exemple, vous disposez d'une liste de chaînes où chaque chaîne peut contenir plus d'un mot, comme une liste de prénoms et noms de famille. Et il est nécessaire de mettre en majuscule la première lettre de chacun de ces mots :

Main.java

Main.java

copy
123456789101112131415161718192021222324
package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Ethan Johnson", "Olivia smith", "mason davis", "Ava taylor", "logan brown", "Emma Anderson", "jackson miller"); System.out.println("List of users: " + users); List<String> list = users.stream() .flatMap(e -> Arrays.stream(e.split(" "))) .map(e -> capitalizeFirstLetter(e)) .toList(); System.out.println("List with capitalized names and surnames: " + list); } private static String capitalizeFirstLetter(String word) { if (word == null || word.isEmpty()) { return word; } return Character.toUpperCase(word.charAt(0)) + word.substring(1); } }

Dans le code ci-dessus, une méthode privée distincte a été écrite pour mettre en majuscule la première lettre d'un mot et cette méthode a été utilisée dans la méthode map() avec une expression lambda.

Notez qu'en utilisant la méthode flatMap, chaque élément du flux est divisé en différents flux à l'aide de la méthode Arrays.stream(e.split(" ")). Comme la méthode split() retourne un tableau, il est nécessaire d'utiliser la méthode Arrays.stream() pour diviser ce tableau en flux.

Ensuite, tous ces flux sont fusionnés en un seul flux, après quoi la méthode écrite précédemment est utilisée. À présent, tous les prénoms et noms de famille des utilisateurs ont la première lettre en majuscule.

Vous savez ce qui serait intéressant ? Mettre ces prénoms et noms de famille dans un HashMap, où la clé est le nom de famille et la valeur est le prénom.

Implémentons cela dans le code :

Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031323334
package com.example; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Ethan Johnson", "Olivia smith", "mason davis", "Ava taylor", "logan brown", "Emma Anderson", "jackson miller"); System.out.println("List of users: " + users); List<String> list = users.stream() .flatMap(e -> Arrays.stream(e.split(" "))) .map(e -> capitalizeFirstLetter(e)) .toList(); System.out.println("List with capitalized names and surnames: " + list); Map<String, String> usersKeyValue = new HashMap<>(); for (int i = 0; i < list.size() - 1; i+=2) { String name = list.get(i); String surname = list.get(i + 1); usersKeyValue.put(surname, name); } System.out.println("Map with surnames as keys and names as values: " + usersKeyValue); } private static String capitalizeFirstLetter(String word) { if (word == null || word.isEmpty()) { return word; } return Character.toUpperCase(word.charAt(0)) + word.substring(1); } }

Avec une boucle simple, les prénoms et noms de famille sont stockés dans des variables puis dans la map. Remarquer le fonctionnement de la boucle. La variable i est incrémentée de 2 à chaque itération car il est nécessaire de sauter le nom de famille une fois qu'il a déjà été enregistré.

  • La méthode distinct() supprime les doublons du flux. En général, cela peut être utile si des éléments uniques dans le flux sont nécessaires ou si l'on souhaite éliminer rapidement les doublons d'une liste. Ceci peut être facilement réalisé avec la construction suivante :
list.stream().distinct().toList()
  • La méthode sorted trie tous les éléments du flux dans l'ordre naturel, du plus petit au plus grand nombre ou par ordre alphabétique. Cela peut également être utile si un flux trié est requis ou pour trier rapidement une liste ;

  • La méthode skip(n) ignore les n premiers éléments du flux. Ceci peut être utile lors du traitement de fichiers texte, où les n premières lignes peuvent, par exemple, représenter des métadonnées ou une description du fichier. Il convient également de mentionner la méthode limit(n), qui généralement limite le nombre d'éléments dans le flux. Même si un flux de 1000 éléments est créé puis limit(200) est utilisé, le flux ne contiendra que les 200 premiers éléments.

Main.java

Main.java

copy
123456789101112
package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); example = example.stream().skip(3).limit(5).toList(); System.out.println("List: " + example); } }

Voici les principales méthodes intermédiaires à utiliser. Vous pouvez explorer les autres méthodes en consultant la lien vers la documentation officielle de Java. Passons maintenant aux méthodes terminales.

Méthodes terminales

  • La méthode terminale que vous connaissez déjà est toList(). Elle convertit le flux en liste et la retourne. Autrement dit, il est possible d’assigner directement ce flux avec méthodes à une liste. Cette méthode a été introduite dans Java 17 et remplace la construction plus complexe collect(Collectors.toList()) ;

  • La méthode collect() convertit également le flux en une structure de données spécifique. Elle utilise, comme paramètre, une méthode de l’interface Collectors. Cette interface propose des méthodes telles que toList(), toSet() et toCollection(). Par exemple :

Main.java

Main.java

copy
123456789101112131415
package com.example; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Set<Integer> integerSet = example.stream().collect(Collectors.toSet()); System.out.println("List: " + example); System.out.println("Set: " + integerSet); } }

La méthode forEach() prend une expression lambda et exécute une action spécifique pour chaque élément du flux.

Par exemple :

Main.java

Main.java

copy
1234567891011
package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); example.stream().forEach(e -> System.out.println(e + 1)); } }

La différence entre cette méthode et la méthode map est que cette méthode est terminale, et après celle-ci, il n'est plus possible d'appeler d'autres méthodes.

Voici toutes les méthodes de base pour travailler avec les flux. Il s'agit d'un sujet complexe, et il se peut que vous ne le compreniez pas immédiatement. Cependant, c'est un sujet qui s'acquiert par la pratique. Dans les prochains chapitres pratiques sur les flux, vous aurez de nombreuses occasions de les manipuler, car c'est une manière très pratique et efficace de manipuler des listes et des tableaux de données !

1. Quel est le principal objectif de l'API Stream en Java ?

2. Laquelle des opérations suivantes est une opération terminale dans l'API Stream ?

3. Que fait l'opération map dans l'API Stream ?

4. En quoi l'opération flatMap diffère-t-elle de map dans l'API Stream ?

5. Que fait l'opération filter dans l'API Stream ?

6. Quel est le but de l'opération forEach dans l'API Stream ?

7. Laquelle des opérations suivantes est une opération intermédiaire dans l'API Stream ?

8. Comment l'opération limit est-elle utilisée dans l'API Stream ?

question mark

Quel est le principal objectif de l'API Stream en Java ?

Select the correct answer

question mark

Laquelle des opérations suivantes est une opération terminale dans l'API Stream ?

Select the correct answer

question mark

Que fait l'opération map dans l'API Stream ?

Select the correct answer

question mark

En quoi l'opération flatMap diffère-t-elle de map dans l'API Stream ?

Select the correct answer

question mark

Que fait l'opération filter dans l'API Stream ?

Select the correct answer

question mark

Quel est le but de l'opération forEach dans l'API Stream ?

Select the correct answer

question mark

Laquelle des opérations suivantes est une opération intermédiaire dans l'API Stream ?

Select the correct answer

question mark

Comment l'opération limit est-elle utilisée dans l'API Stream ?

Select the correct answer

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 4. Chapitre 3

Demandez à l'IA

expand

Demandez à l'IA

ChatGPT

Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion

bookAPI de Flux en Java

Glissez pour afficher le menu

Il existe différentes manières de traiter les données en Java – boucles, méthodes et divers algorithmes. Cependant, avec Java 8, un outil très puissant a été introduit : l’API Stream.

En termes simples, l’API Stream permet de travailler rapidement et facilement avec un flux d’informations. Dans notre cas, ce flux d’informations est représenté par des collections. L’API Stream repose sur certains concepts. Voici les principaux.

Concepts principaux

  • Stream : représente une séquence d’éléments de données pouvant être traités ;

  • Opérations intermédiaires : opérations qui créent un nouveau flux après leur exécution. Exemples : filter, map, distinct, sorted ;

  • Opérations terminales : opérations qui terminent le traitement du flux et retournent un résultat. Exemples : collect, forEach, count, reduce ;

  • Streams parallèles : permettent le traitement parallèle des données. Les méthodes parallel() et parallelStream() sont utilisées pour créer des flux parallèles.

Assez parlé de théorie, passons à la pratique !

La déclaration d'un flux se fait en utilisant une méthode sur la collection que vous souhaitez convertir en flux :

Main.java

Main.java

copy
12
List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream();

Avec la méthode stream(), un flux de chaînes de caractères est obtenu. Cependant, pour commencer à travailler avec le flux, il est nécessaire de comprendre ce que sont les expressions lambda, car les méthodes de flux fonctionnent principalement avec celles-ci.

Expressions Lambda

Les expressions lambda ont été introduites dans Java 8 et représentent une forme simplifiée de création de fonctions anonymes en Java. Les fonctions anonymes n'ont pas été abordées auparavant car elles n'étaient pas particulièrement nécessaires, mais nous allons maintenant les découvrir à travers les expressions lambda.

Syntaxe d'une expression lambda :

La syntaxe générale des expressions lambda en Java est la suivante :

Example.java

Example.java

copy
123
(parameters) -> expression // or (parameters) -> { statements; }
  • Paramètres : il s'agit d'une liste de paramètres qui peut être vide ou contenir un ou plusieurs paramètres ;

  • Flèche : représentée par le symbole ->, qui sépare les paramètres du corps de l'expression lambda ;

  • Expression ou instructions : il s'agit du corps de la fonction, contenant une expression ou un bloc d'instructions.

Voici un exemple d'expression lambda représentant une fonction simple qui additionne deux nombres :

Example.java

Example.java

copy
12345678910
// Traditional way MathOperation addition = new MathOperation() { @Override public int operate(int a, int b) { return a + b; } }; // Using a lambda expression MathOperation addition = (int a, int b) -> a + b;

Examinons de plus près ce qui se passe exactement dans le code ci-dessus et comment nous utilisons les expressions lambda :

Main.java

Main.java

copy
1234567891011121314
package com.example; // Functional interface with a single abstract method interface MyMathOperation { int operate(int a, int b); } public class Main { public static void main(String[] args) { // Using a lambda expression to implement the interface MyMathOperation addition = (a, b) -> a + b; System.out.println("Sum: " + addition.operate(5, 3)); } }

Dans le code ci-dessus :

Création d'une interface fonctionnelle MyMathOperation avec une seule méthode abstraite operate.

Utilisation d'une expression lambda pour implémenter cette méthode, réalisant l'addition de deux nombres.

Affichage du résultat de l'addition.

Il est compréhensible que cela puisse être difficile à saisir pour le moment, mais revenons à l'API Stream, où les expressions lambda sont fréquemment utilisées, et essayons de comprendre comment les utiliser en pratique.

Comme vous vous en souvenez, précédemment, nous avons créé un flux de chaînes de caractères à partir d'une liste de chaînes. Utilisons maintenant les méthodes de flux pour transformer chaque chaîne de ce flux en majuscules :

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream(); stream.map(e -> e.toUpperCase()).toList(); } }

Dans le code ci-dessus, une expression lambda et deux méthodes ont été utilisées : map() et toList(). Si la fonction de la méthode toList() est évidente, la méthode map() modifie chaque élément du flux selon l'expression lambda fournie.

Examinons de plus près le fonctionnement de l'expression lambda dans ce contexte :

La méthode map() applique la méthode toUpperCase() à chaque élément du flux. L’élément de ce flux a été défini comme e et, à l’aide de l’expression lambda, le programme a été instruit d’appliquer cette méthode à chaque élément.

Cependant, ce n’est pas encore terminé car une opération intermédiaire a été appliquée. Cela signifie que les opérations sur le flux ne sont pas encore achevées. Pour finaliser le traitement du flux, il est nécessaire d’appliquer une opération terminale, qui terminera les opérations sur le flux et retournera une valeur spécifique. Par exemple, la méthode toList() peut être utilisée, et le flux modifié sera converti en liste.

Par exemple :

Main.java

Main.java

copy
1234567891011121314
package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream(); List<String> list = stream.map(e -> e.toUpperCase()).toList(); System.out.println(list); } }

Examinons de plus près les opérations intermédiaires possibles dans le flux.

Opérations intermédiaires

La méthode map() — vous connaissez déjà cette méthode ; elle effectue les opérations spécifiées par l'expression lambda sur chaque élément du flux.

Par exemple, utilisons la méthode substring() sur chaque élément d'un flux de chaînes de caractères :

Main.java

Main.java

copy
123456789101112131415
package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); Stream<String> stream = strings.stream(); List<String> list = stream.map(e -> e.substring(1, 4)).toList(); System.out.println("Modified list: " + list); } }

La méthode filter() prend une expression lambda avec une condition selon laquelle le flux sera filtré. Autrement dit, tous les éléments qui remplissent la condition vont rester dans le flux, et les éléments qui ne remplissent pas la condition seront supprimés du flux. Modifions le flux pour ne conserver que les éléments dont la longueur est supérieure à 5 :

Main.java

Main.java

copy
12345678910111213141516
package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); Stream<String> stream = strings.stream(); stream = stream.filter(e -> e.length() > 5); List<String> list = stream.map(e -> e.substring(1, 4)).toList(); System.out.println("Modified list: " + list); } }

En utilisant la méthode filter(), la chaîne de caractères "with" est supprimée du flux car ce mot contient moins de 5 caractères.

Il est également possible d'utiliser plusieurs opérations intermédiaires consécutivement.

Par exemple, le code ci-dessus peut être légèrement simplifié :

Main.java

Main.java

copy
12345678910111213141516
package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); List<String> list = strings.stream() .filter(e -> e.length() > 5) .map(e -> e.substring(1, 4)) .toList(); System.out.println("Modified list: " + list); } }

Lors de l'enchaînement de plusieurs méthodes de flux, il est recommandé de placer chaque méthode sur une nouvelle ligne afin d'améliorer considérablement la lisibilité du code.

La méthode flatMap() transforme chaque élément d'un flux en un nouveau flux et combine les résultats en un seul flux. En d'autres termes, avec cette méthode, il est possible de diviser le flux en plusieurs flux, puis ils seront fusionnés en un seul flux. Par exemple, vous disposez d'une liste de chaînes où chaque chaîne peut contenir plus d'un mot, comme une liste de prénoms et noms de famille. Et il est nécessaire de mettre en majuscule la première lettre de chacun de ces mots :

Main.java

Main.java

copy
123456789101112131415161718192021222324
package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Ethan Johnson", "Olivia smith", "mason davis", "Ava taylor", "logan brown", "Emma Anderson", "jackson miller"); System.out.println("List of users: " + users); List<String> list = users.stream() .flatMap(e -> Arrays.stream(e.split(" "))) .map(e -> capitalizeFirstLetter(e)) .toList(); System.out.println("List with capitalized names and surnames: " + list); } private static String capitalizeFirstLetter(String word) { if (word == null || word.isEmpty()) { return word; } return Character.toUpperCase(word.charAt(0)) + word.substring(1); } }

Dans le code ci-dessus, une méthode privée distincte a été écrite pour mettre en majuscule la première lettre d'un mot et cette méthode a été utilisée dans la méthode map() avec une expression lambda.

Notez qu'en utilisant la méthode flatMap, chaque élément du flux est divisé en différents flux à l'aide de la méthode Arrays.stream(e.split(" ")). Comme la méthode split() retourne un tableau, il est nécessaire d'utiliser la méthode Arrays.stream() pour diviser ce tableau en flux.

Ensuite, tous ces flux sont fusionnés en un seul flux, après quoi la méthode écrite précédemment est utilisée. À présent, tous les prénoms et noms de famille des utilisateurs ont la première lettre en majuscule.

Vous savez ce qui serait intéressant ? Mettre ces prénoms et noms de famille dans un HashMap, où la clé est le nom de famille et la valeur est le prénom.

Implémentons cela dans le code :

Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031323334
package com.example; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Ethan Johnson", "Olivia smith", "mason davis", "Ava taylor", "logan brown", "Emma Anderson", "jackson miller"); System.out.println("List of users: " + users); List<String> list = users.stream() .flatMap(e -> Arrays.stream(e.split(" "))) .map(e -> capitalizeFirstLetter(e)) .toList(); System.out.println("List with capitalized names and surnames: " + list); Map<String, String> usersKeyValue = new HashMap<>(); for (int i = 0; i < list.size() - 1; i+=2) { String name = list.get(i); String surname = list.get(i + 1); usersKeyValue.put(surname, name); } System.out.println("Map with surnames as keys and names as values: " + usersKeyValue); } private static String capitalizeFirstLetter(String word) { if (word == null || word.isEmpty()) { return word; } return Character.toUpperCase(word.charAt(0)) + word.substring(1); } }

Avec une boucle simple, les prénoms et noms de famille sont stockés dans des variables puis dans la map. Remarquer le fonctionnement de la boucle. La variable i est incrémentée de 2 à chaque itération car il est nécessaire de sauter le nom de famille une fois qu'il a déjà été enregistré.

  • La méthode distinct() supprime les doublons du flux. En général, cela peut être utile si des éléments uniques dans le flux sont nécessaires ou si l'on souhaite éliminer rapidement les doublons d'une liste. Ceci peut être facilement réalisé avec la construction suivante :
list.stream().distinct().toList()
  • La méthode sorted trie tous les éléments du flux dans l'ordre naturel, du plus petit au plus grand nombre ou par ordre alphabétique. Cela peut également être utile si un flux trié est requis ou pour trier rapidement une liste ;

  • La méthode skip(n) ignore les n premiers éléments du flux. Ceci peut être utile lors du traitement de fichiers texte, où les n premières lignes peuvent, par exemple, représenter des métadonnées ou une description du fichier. Il convient également de mentionner la méthode limit(n), qui généralement limite le nombre d'éléments dans le flux. Même si un flux de 1000 éléments est créé puis limit(200) est utilisé, le flux ne contiendra que les 200 premiers éléments.

Main.java

Main.java

copy
123456789101112
package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); example = example.stream().skip(3).limit(5).toList(); System.out.println("List: " + example); } }

Voici les principales méthodes intermédiaires à utiliser. Vous pouvez explorer les autres méthodes en consultant la lien vers la documentation officielle de Java. Passons maintenant aux méthodes terminales.

Méthodes terminales

  • La méthode terminale que vous connaissez déjà est toList(). Elle convertit le flux en liste et la retourne. Autrement dit, il est possible d’assigner directement ce flux avec méthodes à une liste. Cette méthode a été introduite dans Java 17 et remplace la construction plus complexe collect(Collectors.toList()) ;

  • La méthode collect() convertit également le flux en une structure de données spécifique. Elle utilise, comme paramètre, une méthode de l’interface Collectors. Cette interface propose des méthodes telles que toList(), toSet() et toCollection(). Par exemple :

Main.java

Main.java

copy
123456789101112131415
package com.example; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Set<Integer> integerSet = example.stream().collect(Collectors.toSet()); System.out.println("List: " + example); System.out.println("Set: " + integerSet); } }

La méthode forEach() prend une expression lambda et exécute une action spécifique pour chaque élément du flux.

Par exemple :

Main.java

Main.java

copy
1234567891011
package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); example.stream().forEach(e -> System.out.println(e + 1)); } }

La différence entre cette méthode et la méthode map est que cette méthode est terminale, et après celle-ci, il n'est plus possible d'appeler d'autres méthodes.

Voici toutes les méthodes de base pour travailler avec les flux. Il s'agit d'un sujet complexe, et il se peut que vous ne le compreniez pas immédiatement. Cependant, c'est un sujet qui s'acquiert par la pratique. Dans les prochains chapitres pratiques sur les flux, vous aurez de nombreuses occasions de les manipuler, car c'est une manière très pratique et efficace de manipuler des listes et des tableaux de données !

1. Quel est le principal objectif de l'API Stream en Java ?

2. Laquelle des opérations suivantes est une opération terminale dans l'API Stream ?

3. Que fait l'opération map dans l'API Stream ?

4. En quoi l'opération flatMap diffère-t-elle de map dans l'API Stream ?

5. Que fait l'opération filter dans l'API Stream ?

6. Quel est le but de l'opération forEach dans l'API Stream ?

7. Laquelle des opérations suivantes est une opération intermédiaire dans l'API Stream ?

8. Comment l'opération limit est-elle utilisée dans l'API Stream ?

question mark

Quel est le principal objectif de l'API Stream en Java ?

Select the correct answer

question mark

Laquelle des opérations suivantes est une opération terminale dans l'API Stream ?

Select the correct answer

question mark

Que fait l'opération map dans l'API Stream ?

Select the correct answer

question mark

En quoi l'opération flatMap diffère-t-elle de map dans l'API Stream ?

Select the correct answer

question mark

Que fait l'opération filter dans l'API Stream ?

Select the correct answer

question mark

Quel est le but de l'opération forEach dans l'API Stream ?

Select the correct answer

question mark

Laquelle des opérations suivantes est une opération intermédiaire dans l'API Stream ?

Select the correct answer

question mark

Comment l'opération limit est-elle utilisée dans l'API Stream ?

Select the correct answer

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 4. Chapitre 3
some-alt