Introduction aux flux Java 8

Introduction aux flux Java 8

1. Vue d'ensemble

Dans cet article, nous allons jeter un coup d'œil à l'une des principales nouvelles fonctionnalités ajoutées par Java 8: les flux.

Nous expliquerons en quoi consistent les flux et présenterons la création et les opérations de base des flux avec des exemples simples.

2. API de flux

L'une des nouvelles fonctionnalités majeures de Java 8 est l'introduction de la fonctionnalité de flux -java.util.stream - qui contient des classes pour traiter des séquences d'éléments.

La classe d'API centrale est leStream<T>.. La section suivante montre comment créer des flux à l'aide des sources de fournisseur de données existantes.

2.1. Création de flux

Les flux peuvent être créés à partir de différentes sources d'éléments, par exemple. collection ou tableau à l'aide des méthodesstream() etof():

String[] arr = new String[]{"a", "b", "c"};
Stream stream = Arrays.stream(arr);
stream = Stream.of("a", "b", "c");

Une méthode par défaut destream() est ajoutée à l'interfaceCollection et permet de créer unStream<T> en utilisant n'importe quelle collection comme source d'élément:

Stream stream = list.stream();

2.2. Multi-threading avec Streams

L'API Stream simplifie également le multithreading en fournissant la méthodeparallelStream() qui exécute les opérations sur les éléments du flux en mode parallèle.

Le code ci-dessous permet d'exécuter la méthodedoWork() en parallèle pour chaque élément du flux:

list.parallelStream().forEach(element -> doWork(element));

Dans la section suivante, nous présenterons certaines des opérations de base de l’API de flux.

3. Opérations de flux

Il existe de nombreuses opérations utiles pouvant être effectuées sur un flux.

Ils sont divisés enintermediate operations (retourneStream<T>) etterminal operations (retourne un résultat de type défini). Les opérations intermédiaires permettent l'enchaînement.

Il convient également de noter que les opérations sur les flux ne changent pas la source.

Voici un exemple rapide:

long count = list.stream().distinct().count();

Ainsi, la méthodedistinct() représente une opération intermédiaire, qui crée un nouveau flux d'éléments uniques du flux précédent. Et la méthodecount() est une opération de terminal, qui renvoie la taille du flux.

3.1. Itérer

L'API Stream permet de remplacer les bouclesfor, for-each etwhile. Il permet de se concentrer sur la logique des opérations, mais pas sur l’itération sur la séquence d’éléments. Par exemple:

for (String string : list) {
    if (string.contains("a")) {
        return true;
    }
}

Ce code peut être modifié avec une seule ligne de code Java 8:

boolean isExist = list.stream().anyMatch(element -> element.contains("a"));

3.2. Filtration

La méthodefilter() nous permet de sélectionner un flux d'éléments qui satisfont un prédicat.

Par exemple, considérons la liste suivante:

ArrayList list = new ArrayList<>();
list.add("One");
list.add("OneAndOnly");
list.add("Derek");
list.add("Change");
list.add("factory");
list.add("justBefore");
list.add("Italy");
list.add("Italy");
list.add("Thursday");
list.add("");
list.add("");

Le code suivant crée unStream<String> desList<String>, trouve tous les éléments de ce flux qui contiennent deschar “d” et crée un nouveau flux contenant uniquement les éléments filtrés:

Stream stream = list.stream().filter(element -> element.contains("d"));

3.3. Cartographie

Pour convertir des éléments d'unStream en leur appliquant une fonction spéciale et pour collecter ces nouveaux éléments en unStream, nous pouvons utiliser la méthodemap():

List uris = new ArrayList<>();
uris.add("C:\\My.txt");
Stream stream = uris.stream().map(uri -> Paths.get(uri));

Ainsi, le code ci-dessus convertitStream<String> enStream<Path> en appliquant une expression lambda spécifique à chaque élément desStream initiaux.

Si vous avez un flux dans lequel chaque élément contient sa propre séquence d'éléments et que vous souhaitez créer un flux de ces éléments internes, vous devez utiliser la méthodeflatMap():

List details = new ArrayList<>();
details.add(new Detail());
Stream stream
  = details.stream().flatMap(detail -> detail.getParts().stream());

Dans cet exemple, nous avons une liste d'éléments de typeDetail. La classeDetail contient un champPARTS, qui est unList<String>. à l'aide desflatMap() méthode, chaque élément du champPARTS sera extrait et ajouté au nouveau flux résultant. Après cela, lesStream<Detail> initiaux seront perdus.

3.4. Correspondant à

Stream API fournit un ensemble d'instruments utiles pour valider les éléments d'une séquence en fonction d'un prédicat. Pour ce faire, l'une des méthodes suivantes peut être utilisée:anyMatch(), allMatch(), noneMatch(). Leurs noms s'expliquent d'eux-mêmes. Ce sont des opérations terminales qui retournent un booléen.

boolean isValid = list.stream().anyMatch(element -> element.contains("h")); // true
boolean isValidOne = list.stream().allMatch(element -> element.contains("h")); // false
boolean isValidTwo = list.stream().noneMatch(element -> element.contains("h")); // false

3.5. Réduction

L'API Stream permet de réduire une séquence d'éléments à une certaine valeur selon une fonction spécifiée à l'aide de la méthodereduce() de typeStream. Cette méthode prend deux paramètres: la première - valeur initiale, la deuxième - une fonction accumulateur.

Imaginez que vous ayez unList<Integer> et que vous vouliez avoir une somme de tous ces éléments et de quelquesInteger initiaux (dans cet exemple 23). Ainsi, vous pouvez exécuter le code suivant et le résultat sera 26 (23 + 1 + 1 + 1).

List integers = Arrays.asList(1, 1, 1);
Integer reduced = integers.stream().reduce(23, (a, b) -> a + b);

3.6. La collecte

La réduction peut également être fournie par la méthodecollect() de typeStream. Cette opération est très pratique en cas de conversion d'un flux en unCollection ou unMap et représentant un flux sous la forme d'une seule chaîne. Il existe une classe d'utilitéCollectors qui fournit une solution pour presque toutes les opérations de collecte typiques. Pour certaines tâches non triviales, unCollector personnalisé peut être créé.

List resultList
  = list.stream().map(element -> element.toUpperCase()).collect(Collectors.toList());

Ce code utilise l'opération du terminalcollect() pour réduire unStream<String> enList<String>.

4. Conclusions

Dans cet article, nous avons brièvement abordé les flux Java - certainement l’une des fonctionnalités les plus intéressantes de Java 8.

Il existe des exemples beaucoup plus avancés d'utilisation de Streams; Le but de cet article était uniquement de fournir une introduction rapide et pratique à ce que vous pouvez faire avec la fonctionnalité et comme point de départ pour explorer et approfondir vos connaissances.

Le code source accompagnant l'article est disponibleover on GitHub.