Maison >Java >javaDidacticiel >Maîtriser les flux Java : un guide complet pour les développeurs

Maîtriser les flux Java : un guide complet pour les développeurs

Linda Hamilton
Linda Hamiltonoriginal
2024-11-27 19:53:10893parcourir

Mastering Java Streams: A Complete Guide for Developers

Java Streams, introduit dans Java 8, est l'un des ajouts les plus puissants au langage. Ils permettent des opérations de style fonctionnel sur des collections et des séquences, transformant ainsi notre approche du traitement des données en Java. Les flux simplifient les tâches telles que le filtrage, le mappage et la collecte de données tout en prenant également en charge les opérations parallèles pour améliorer les performances. Dans cet article, nous explorerons les principes fondamentaux de Streams, discuterons des types d'opérations qu'ils prennent en charge et fournirons des exemples pour vous aider à tirer le meilleur parti de cette fonctionnalité essentielle.

Table des matières

1.  What is Streams and why we need it?
2.  Types of Streams: Intermediate vs. Terminal
3.  Creating Streams in Java
4.  Intermediate Stream Operations
5.  Terminal Stream Operations
6.  Using Streams with Lambdas
7.  Conclusion

Qu’est-ce que Streams et pourquoi en avons-nous besoin ?

Les flux en Java offrent un moyen puissant de traiter des collections de données. Ils nous permettent d'effectuer des opérations fonctionnelles sur les éléments d'une collection, comme le filtrage et la transformation, sans muter les données sous-jacentes. Les flux aident les développeurs à se concentrer sur ce qu'ils veulent réaliser, plutôt que sur la manière d'y parvenir, en fournissant une abstraction de niveau supérieur pour le traitement des données.

Les flux ont été introduits dans Java 8 aux côtés des expressions lambda et des interfaces fonctionnelles, conçues pour rendre Java plus expressif et réduire le code passe-partout. En incorporant des flux, Java a commencé à adopter le paradigme de programmation fonctionnelle, permettant un code plus propre et plus concis.

Principaux avantages des flux

  • Traitement déclaratif des données : décrivez les opérations que vous souhaitez effectuer, plutôt que de gérer manuellement les boucles et les conditions.
  • Immuabilité et apatride : les opérations de flux ne modifient pas la structure des données source.
  • Traitement parallèle : prise en charge des flux parallèles, permettant de répartir facilement les opérations sur plusieurs threads.

Types de flux : intermédiaire ou terminal

Les flux sont classés en deux types principaux :

  • Opérations intermédiaires : ces opérations transforment le flux, renvoyant ainsi un autre flux. Ils sont paresseux, ce qui signifie qu'ils ne sont pas exécutés tant qu'une opération de terminal n'est pas appelée.
  • Opérations de terminal : ces opérations déclenchent le traitement des données du flux et renvoient un résultat non-flux (par exemple, une collection, une valeur unique ou un booléen). Une fois qu'une opération de terminal est exécutée, le flux est considéré comme consommé et ne peut pas être réutilisé.

Exemple :

List<String> names = List.of("Alice", "Bob", "Charlie", "David");

// Intermediate (lazy) operations: filter and map
Stream<String> stream = names.stream()
                             .filter(name -> name.startsWith("A"))
                             .map(String::toUpperCase);

// Terminal operation: collect
List<String> filteredNames = stream.collect(Collectors.toList());
System.out.println(filteredNames); // Output: [ALICE]

Dans cet exemple, filter et map sont des opérations intermédiaires qui ne seront exécutées que lorsque l'opération de terminal collect est appelée.

Création de flux en Java

Java propose plusieurs façons de créer des flux, ce qui facilite le démarrage du traitement des données.

  • Des collections

La manière la plus courante de créer des flux consiste à utiliser des collections telles que List, Set et Map.

1.  What is Streams and why we need it?
2.  Types of Streams: Intermediate vs. Terminal
3.  Creating Streams in Java
4.  Intermediate Stream Operations
5.  Terminal Stream Operations
6.  Using Streams with Lambdas
7.  Conclusion
  • À partir de tableaux
List<String> names = List.of("Alice", "Bob", "Charlie", "David");

// Intermediate (lazy) operations: filter and map
Stream<String> stream = names.stream()
                             .filter(name -> name.startsWith("A"))
                             .map(String::toUpperCase);

// Terminal operation: collect
List<String> filteredNames = stream.collect(Collectors.toList());
System.out.println(filteredNames); // Output: [ALICE]
  • Utiliser Stream.of
List<String> names = List.of("Alice", "Bob", "Charlie");
Stream<String> nameStream = names.stream();
  • Flux infinis (flux générés)

Java permet de créer des flux infinis à l'aide de Stream.generate et Stream.iterate.

String[] namesArray = {"Alice", "Bob", "Charlie"};
Stream<String> nameStream = Arrays.stream(namesArray);

Opérations de flux intermédiaire

Les opérations intermédiaires renvoient un nouveau flux et sont paresseuses. Cela signifie qu'ils ne sont exécutés que lorsqu'une opération de terminal est appelée.

  • filtre(Prédicat)

Filtre les éléments en fonction d'une condition.

Stream<String> stream = Stream.of("Alice", "Bob", "Charlie");
  • carte(Fonction)

Transforme les éléments d'un type à un autre.

Stream<Double> randomNumbers = Stream.generate(Math::random).limit(5);
Stream<Integer> counting = Stream.iterate(0, n -> n + 1).limit(5);
  • triés(Comparateur)

Trie les éléments dans l'ordre naturel ou en fonction d'un comparateur.

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
                                   .filter(n -> n % 2 == 0)
                                   .collect(Collectors.toList());
  • coup d'oeil (Consommateur)

Effectue une action sur chaque élément, souvent utile pour le débogage.

List<String> names = List.of("Alice", "Bob");
List<Integer> nameLengths = names.stream()
                                 .map(String::length)
                                 .collect(Collectors.toList());

Opérations du flux terminal

Les opérations du terminal sont exécutées en dernier, déclenchant le traitement réel des données et renvoyant un résultat final.

  • pourEach(Consumer)

Exécute une action pour chaque élément du flux.

List<String> names = List.of("Bob", "Alice", "Charlie");
List<String> sortedNames = names.stream()
                                .sorted()
                                .collect(Collectors.toList());
  • collecter(Collectionneur)

Collecte les éléments d'un flux dans une collection, une liste, un ensemble ou d'autres structures de données.

List<String> names = List.of("Alice", "Bob");
names.stream()
     .peek(name -> System.out.println("Processing " + name))
     .collect(Collectors.toList());
  • compte()

Compte le nombre d'éléments dans le flux.

List<String> names = List.of("Alice", "Bob");
names.stream().forEach(System.out::println);
  • anyMatch (Prédicat), allMatch (Prédicat), noneMatch (Prédicat)

Vérifie si l'un, la totalité ou aucun des éléments ne correspond à une condition donnée.

List<String> names = List.of("Alice", "Bob");
Set<String> nameSet = names.stream().collect(Collectors.toSet());
  • findFirst() et findAny()

Renvoie un facultatif décrivant le premier ou n'importe quel élément du flux.

List<String> names = List.of("Alice", "Bob");
long count = names.stream().count();

Utiliser des flux avec Lambdas

Les flux et les expressions lambda vont de pair. Étant donné que les flux sont basés sur des interfaces fonctionnelles, ils fonctionnent de manière transparente avec les lambdas, permettant un traitement de données expressif et concis.

Par exemple, filtrer une liste de noms pour trouver des noms commençant par « A », puis les convertir en majuscules :

List<String> names = List.of("Alice", "Bob", "Charlie");
boolean hasAlice = names.stream().anyMatch(name -> name.equals("Alice"));

Dans cet exemple :

  • le filtre prend un nom lambda -> name.startsWith("A") pour filtrer les noms.
  • map prend une référence de méthode String::toUpperCase pour convertir les noms en majuscules.

Conclusion

Java Streams apporte des capacités de programmation fonctionnelles à Java, permettant une manipulation de données expressive et concise. En comprenant la différence entre les opérations intermédiaires et terminales et comment créer et utiliser efficacement des flux, vous pouvez améliorer considérablement la lisibilité et la maintenabilité de votre code. Intégrez des flux et des lambdas dans votre flux de travail pour écrire des applications Java plus propres et plus efficaces.

Bon streaming !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn