API Java 8 Streams peek ()

1. Introduction

L'API Java Stream nous présente une alternative puissante pour le traitement des données.

Dans ce court tutoriel, nous nous concentrerons sur peek () , une méthode souvent mal comprise.

2. Exemple rapide

Mettons nos mains sales et essayons d'utiliser peek () . Nous avons un flux de noms et nous voulons les imprimer sur la console.

Puisque peek () attend un consommateur comme seul argument, cela semble être un bon ajustement, alors essayons:

Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); nameStream.peek(System.out::println);

Cependant, l'extrait de code ci-dessus ne produit aucune sortie. Pour comprendre pourquoi, faisons un rappel rapide sur les aspects du cycle de vie des flux.

3. Opérations intermédiaires vs terminaux

Rappelez-vous que les flux se composent de trois parties: une source de données, zéro ou plusieurs opérations intermédiaires et zéro ou une opération de terminal.

La source fournit les éléments au pipeline.

Les opérations intermédiaires récupèrent les éléments un par un et les traitent. Toutes les opérations intermédiaires sont paresseuses et, par conséquent, aucune opération n'aura d'effet jusqu'à ce que le pipeline commence à fonctionner.

Les opérations de terminal signifient la fin du cycle de vie du flux. Plus important encore pour notre scénario, ils lancent les travaux en cours .

4. Utilisation de peek ()

La raison pour laquelle peek () n'a pas fonctionné dans notre premier exemple est qu'il s'agit d'une opération intermédiaire et que nous n'avons pas appliqué d' opération de terminal au pipeline. Alternativement, nous aurions pu utiliser forEach () avec le même argument pour obtenir le comportement souhaité:

Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); nameStream.forEach(System.out::println);

La page Javadoc de peek () dit: « Cette méthode existe principalement pour prendre en charge le débogage, où vous voulez voir les éléments à mesure qu'ils passent à un certain point dans un pipeline ».

Considérons cet extrait de la même page Javadoc:

Stream.of("one", "two", "three", "four") .filter(e -> e.length() > 3) .peek(e -> System.out.println("Filtered value: " + e)) .map(String::toUpperCase) .peek(e -> System.out.println("Mapped value: " + e)) .collect(Collectors.toList());

Il montre comment nous observons les éléments qui ont passé chaque opération.

En plus de cela, peek () peut être utile dans un autre scénario: lorsque nous voulons modifier l'état interne d'un élément . Par exemple, disons que nous voulons convertir le nom de tous les utilisateurs en minuscules avant de les imprimer:

Stream userStream = Stream.of(new User("Alice"), new User("Bob"), new User("Chuck")); userStream.peek(u -> u.setName(u.getName().toLowerCase())) .forEach(System.out::println);

Alternativement, nous aurions pu utiliser map () , mais peek () est plus pratique car nous ne voulons pas remplacer l'élément.

5. Conclusion

Dans ce court didacticiel, nous avons vu un résumé du cycle de vie du flux pour comprendre le fonctionnement de peek () . Nous avons également vu deux cas d'utilisation quotidiens lorsque l'utilisation de peek () est l'option la plus simple.

Et comme d'habitude, les exemples sont disponibles sur sur GitHub.