Java Collect() : apprenez à utiliser les opérations de réduction

Les Collectors d’un Stream sont une fonction puissante de l’API Stream de Java 8 grâce à laquelle vous pouvez rassembler et traiter efficacement les données. Nous vous expliquons la structure et les possibilités d’utilisation de la méthode Collect de Java.

Quels sont les domaines d’application de Java Collect() ?

Un Collector d’un Stream peut être utilisé pour créer une liste, un ensemble ou une carte à partir d’un Stream. Un Stream est une séquence d’éléments traités les uns à la suite des autres. L’interface Collector propose un ensemble d’opérations de réduction pour les données du pipeline d’un Stream. Il s’agit d’opérations finales qui collectent et rassemblent les résultats des étapes intermédiaires.

Les Collectors peuvent par exemple être utilisés pour filtrer ou trier des objets dans un Stream. Il est également possible de procéder à une agrégation, par exemple additionner des nombres, regrouper des chaînes ou compter des éléments. En outre, les Collectors disposent de fonctions permettant de transformer le contenu d’un Stream en une structure spécifique. Vous pouvez donc par exemple convertir une liste en une carte. Les regroupements aident à catégoriser les éléments présentant les mêmes caractéristiques ou conditions. Mais avant tout, les Collectors d’un Stream ont l’avantage de traiter les données en parallèle sur plusieurs threads. Les opérations peuvent ainsi être exécutées bien plus rapidement et efficacement, notamment pour d’importants volumes de données.

Syntaxe de Java Collect()

La méthode accepte comme argument un Collector qui définit comment les éléments du Stream doivent être recueillis et agrégés. Un Collector est une interface qui met à disposition diverses méthodes visant à réunir les éléments d’un Stream sous une forme spécifique, par exemple une liste, un ensemble ou une carte.

Il existe deux types de méthodes Collect en Java :

  1. <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner)
  2. <R, A> R collect(Collector<? super T, A, R> collector)

La première variante possède trois fonctions comme argument :

  • supplier : crée un conteneur qui sera utilisé pour le résultat intermédiaire.
  • accumulator : calcule le résultat final.
  • combiner : combine les résultats des opérations parallèles du Stream.

Ces Collectors prédéfinis sont déjà inclus dans la bibliothèque standard et peuvent facilement être importés et utilisés.

La deuxième variante utilise un Collector comme argument et renvoie le résultat.

  • R : le type du résultat
  • T : le type des éléments dans le Stream
  • A : le type de la fonction accumulator qui enregistre l’état intermédiaire de l’opération du Collector
  • collector : exécute l’opération de réduction

En utilisant ces variantes, les développeurs peuvent créer des Collectors sur mesure spécialement conçus selon leurs exigences et offrant un niveau élevé de flexibilité et de contrôle sur le processus de réduction.

Exemples pratiques d’utilisation de Java Collect()

Nous illustrons ci-après plusieurs fonctions de la méthode « Stream.collect() ». Vous devez déjà être familiarisé avec les opérateurs Java basiques avant de passer au Collection Framework.

Lier une liste de chaînes de caractères

Avec Collect() en Java, vous pouvez concaténer une liste de chaînes de caractères pour obtenir une nouvelle chaîne de caractères :

List<String> letters = List.of("a", "b", "c", "d", "e");
// sans la fonction combiner
StringBuilder result = letters.stream().collect(StringBuilder::new, (x, y) -> x.append(y),
    (a, b) -> a.append(",").append(b));
System.out.println(result.toString());
// avec la fonction combiner
StringBuilder result1 = letters.parallelStream().collect(StringBuilder::new, (x, y) -> x.append(y),
    (a, b) -> a.append(",").append(b));
System.out.println(result1.toString());
Java

Nous obtenons le résultat suivant :

abcde
a, b, c, d, e
Java

Dans le premier calcul se trouve seulement une instance de StringBuilder qui n’utilise pas la fonction combiner. C’est pourquoi le résultat obtenu est « abcde ».

Dans le deuxième résultat, nous constatons que la fonction combiner réunit les instances StringBuilder et les sépare par une virgule.

Réunir des éléments en une liste via toList()

Grâce à la fonction « filter() », nous pouvons sélectionner des éléments spécifiques dans une liste et les enregistrer dans une nouvelle liste avec « toList() ».

List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
List<Integer> oddNumbers = numbers.stream().filter(x -> x % 2 != 0).collect(Collectors.toList());
System.out.println(oddNumbers);
Java

La nouvelle liste contient à présent uniquement les nombres impairs :

[1, 3, 5, 7]
Java

Réunir des éléments en un ensemble via toSet()

De la même manière, nous pouvons créer un nouvel ensemble à partir des éléments sélectionnés. Dans un ensemble, les données sont désordonnées.

List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
Set<Integer> evenNumbers = numbers.parallelStream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
System.out.println(evenNumbers);
Java

Le résultat est le suivant :

[2, 4, 6]
Java

Réunir des éléments en une carte via toMap()

Une carte associée à Collect() en Java affecte une valeur à chaque clé.

List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
Map<Integer, String> mapEvenNumbers = numbers.parallelStream().filter(x -> x % 2 == 0)
    .collect(Collectors.toMap(Function.identity(), x -> String.valueOf(x)));
System.out.println(mapEvenNumbers);
Java

Dans le résultat, nous constatons que l’entrée, composée de chiffres pairs, s’est vue affectée des valeurs identiques :

{2=2, 4=4, 6=6}
Java

Combiner des éléments en une chaîne de caractères via joining()

La méthode « joining() » ajoute chaque élément du Stream dans l’ordre dans lequel il apparaît et utilise un séparateur pour séparer les éléments. Le séparateur est indiqué en tant qu’argument de « joining() ». Si aucun séparateur n’est indiqué, « joining() » utilise la chaîne vide « “” ».

jshell> String result1 = Stream.of("a", "b", "c").collect(Collectors.joining());
jshell> String result2 = Stream.of("a", "b", "c").collect(Collectors.joining(",", "{", "}"));
Java

Le résultat est le suivant :

result1 ==> "abc"
result2 ==> "{a,b,c}"
Java