Partage de technologie

Explication détaillée de l'API Java Stream : un outil puissant pour un traitement efficace des données de collecte

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

introduction

Java 8 introduit de nombreuses nouvelles fonctionnalités, dont les plus notables sont les expressions Lambda et l'API Stream. L'API Stream fournit une méthode efficace et concise pour traiter les données de collecte, rendant le code plus concis et clair, et offre une lisibilité et une maintenabilité élevées. Cet article approfondira l'utilisation de l'API Java Stream, y compris les concepts de base, les opérations courantes, le traitement parallèle, les cas pratiques et les meilleures pratiques.

Table des matières

  1. Qu'est-ce que l'API Stream ?
  2. Opérations de base de l'API Stream
  3. Opérations avancées de l'API Stream
  4. Flux parallèle
  5. Cas pratique de l'API Stream
  6. Meilleures pratiques pour les API Stream
  7. Foire aux questions et solutions
  8. Résumer

Qu'est-ce que l'API Stream ?

L'API Stream est une abstraction introduite dans Java 8 pour le traitement des données de collecte qui permet de traiter les données de manière déclarative (similaire aux instructions SQL). L'API Stream fournit de nombreuses opérations puissantes qui peuvent être utilisées pour filtrer, trier, mapper, réduire et d'autres opérations sur les collections, simplifiant considérablement le code.

Caractéristiques

  • programmation déclarative : utilisez l'API Stream pour écrire du code de manière déclarative, réduisant ainsi le code passe-partout.
  • appel en chaîne: Les opérations de l'API Stream peuvent être appelées en chaîne, améliorant la lisibilité du code.
  • évaluation paresseuse: Les opérations intermédiaires sont évaluées paresseusement et ne sont évaluées que lorsque l'opération terminale est effectuée.
  • traitement parallèle: Prend en charge le traitement parallèle et peut tirer pleinement parti des processeurs multicœurs.

Opérations de base de l'API Stream

Créer un flux

L'API Stream propose diverses méthodes pour créer un flux. Les méthodes courantes sont les suivantes :

  1. Créer à partir d'une collection
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
  • 1
  • 2
  1. Créer à partir d'un tableau
String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
  • 1
  • 2
  1. utiliserStream.of
Stream<String> stream = Stream.of("a", "b", "c");
  • 1
  1. utiliserStream.generate
Stream<Double> stream = Stream.generate(Math::random).limit(10);
  • 1
  1. utiliserStream.iterate
Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(10);
  • 1

opérations intermédiaires

Les opérations intermédiaires sont utilisées pour convertir Stream et sont évaluées paresseusement. Les opérations intermédiaires courantes sont les suivantes :

  1. filter: utilisé pour filtrer les éléments.
Stream<String> stream = list.stream().filter(s -> s.startsWith("a"));
  • 1
  1. map: Utilisé pour mapper chaque élément au résultat correspondant.
Stream<String> stream = list.stream().map(String::toUpperCase);
  • 1
  1. flatMap: Utilisé pour convertir chaque élément en Stream, puis le fusionner en un seul Stream.
Stream<String> stream = list.stream().flatMap(s -> Stream.of(s.split("")));
  • 1
  1. distinct: Utilisé pour supprimer les doublons.
Stream<String> stream = list.stream().distinct();
  • 1
  1. sorted: utilisé pour le tri.
Stream<String> stream = list.stream().sorted();
  • 1
  1. peek: Utilisé pour visualiser chaque élément pendant le traitement.
Stream<String> stream = list.stream().peek(System.out::println);
  • 1

Fonctionnement des terminaux

Les opérations de terminal sont utilisées pour démarrer le calcul de Stream et générer des résultats. Les opérations de terminal courantes sont les suivantes :

  1. forEach: Effectuer une opération sur chaque élément.
list.stream().forEach(System.out::println);
  • 1
  1. collect: Convertir le flux en d'autres formulaires.
List<String> result = list.stream().collect(Collectors.toList());
  • 1
  1. reduce: Réduisez les éléments du Stream en une valeur.
Optional<String> result = list.stream().reduce((s1, s2) -> s1 + s2);
  • 1
  1. toArray: Convertir le flux en tableau.
String[] array = list.stream().toArray(String[]::new);
  • 1
  1. count: Comptez le nombre d'éléments.
long count = list.stream().count();
  • 1
  1. anyMatchallMatchnoneMatch: Utilisé pour faire correspondre le jugement.
boolean anyMatch = list.stream().anyMatch(s -> s.startsWith("a"));
boolean allMatch = list.stream().allMatch(s -> s.startsWith("a"));
boolean noneMatch = list.stream().noneMatch(s -> s.startsWith("a"));
  • 1
  • 2
  • 3
  1. findFirstfindAny: Utilisé pour rechercher des éléments.
Optional<String> first = list.stream().findFirst();
Optional<String> any = list.stream().findAny();
  • 1
  • 2

Opérations avancées de l'API Stream

trier

utilisersortedLa méthode trie le Stream et peut passer dans un comparateur.

List<String> list = Arrays.asList("b", "c", "a");
List<String> sortedList = list.stream().sorted().collect(Collectors.toList());
// 逆序排序
List<String> sortedListDesc = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
  • 1
  • 2
  • 3
  • 4

filtre

utiliserfilterMéthode pour filtrer les éléments dans Stream.

List<String> list = Arrays.asList("a", "b", "c");
List<String> filteredList = list.stream().filter(s -> s.startsWith("a")).collect(Collectors.toList());
  • 1
  • 2

cartographie

utilisermapLa méthode mappe les éléments du Stream.

List<String> list = Arrays.asList("a", "b", "c");
List<String> mappedList = list.stream().map(String::toUpperCase).collect(Collectors.toList());
  • 1
  • 2

Loi

utiliserreduceMéthode pour réduire les éléments du Stream.

List<String> list = Arrays.asList("a", "b", "c");
String result = list.stream().reduce("", (s1, s2) -> s1 + s2);
  • 1
  • 2

collecter

utilisercollectLes méthodes convertissent Stream en d’autres formes.

List<String> list = Arrays.asList("a", "b", "c");
List<String> collectedList = list.stream().collect(Collectors.toList());
Set<String> collectedSet = list.stream().collect(Collectors.toSet());
String joinedString = list.stream().collect(Collectors.joining(","));
  • 1
  • 2
  • 3
  • 4

Flux parallèle

Parallel Stream peut exploiter pleinement les avantages des processeurs multicœurs pour améliorer l'efficacité du traitement des données.peut utiliserparallelStreamLa méthode crée un flux parallèle.

List<String> list = Arrays.asList("a", "b", "c");
List<String> parallelList = list.parallelStream().map(String::toUpperCase).collect(Collectors.toList());
  • 1
  • 2

Peut également être utiliséparallelLa méthode convertit un Stream normal en Stream parallèle.

List<String> list = Arrays.asList("a", "b", "c");
List<String> parallelList = list.stream().parallel().map(String::toUpperCase).collect(Collectors.toList());
  • 1
  • 2

Il convient de noter que le flux parallèle n'est pas toujours plus rapide que le flux série et qu'il doit être testé en fonction de la situation spécifique.

Cas pratique de l'API Stream

Traitement des données de collecte

Cas 1 : Filtrer et transformer des collections

Étant donné une collection de chaînes, filtrez les chaînes dont la longueur est inférieure à 3 et convertissez les chaînes restantes en majuscules.

List<String> list = Arrays.asList("a", "ab", "abc", "abcd");
List<String> result = list.stream()
    .filter(s -> s.length() >= 3)
    .map(String::toUpperCase)
    .collect(Collectors.toList());
System.out.println(result); // 输出:[ABC, ABCD]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
Cas 2 : Calculer la moyenne

Étant donné un ensemble d’entiers, calculez la moyenne de tous les entiers.

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
OptionalDouble average = list.stream()
    .mapToInt(Integer::intValue)
    .average();
average.ifPresent(System.out::println); // 输出:3.0
  • 1
  • 2
  • 3
  • 4
  • 5

Opérations sur les fichiers

Cas 3 : Lire le contenu du fichier

Utilisation de l'API Stream

Lisez le contenu du fichier et affichez-le sur la console.

try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {
    lines.forEach(System.out::println);
} catch (IOException e) {
    e.printStackTrace();
}
  • 1
  • 2
  • 3
  • 4
  • 5
Cas 4 : comptez le nombre d'occurrences de mots

Lisez le contenu du fichier et comptez le nombre d'occurrences de chaque mot.

try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {
    Map<String, Long> wordCount = lines
        .flatMap(line -> Arrays.stream(line.split("\W+")))
        .collect(Collectors.groupingBy(String::toLowerCase, Collectors.counting()));
    wordCount.forEach((word, count) -> System.out.println(word + ": " + count));
} catch (IOException e) {
    e.printStackTrace();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Opérations de base de données

Cas 5 : Traitement des résultats des requêtes de base de données

Disons que nous avons une table de base de donnéesusers, contenant des champsidnameetage . Nous pouvons utiliser l'API Stream pour traiter les résultats de la requête.

List<User> users = queryDatabase();
List<String> names = users.stream()
    .filter(user -> user.getAge() > 18)
    .map(User::getName)
    .collect(Collectors.toList());
System.out.println(names);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Meilleures pratiques pour les API Stream

  1. Évitez la parallélisation inutile: Parallel Stream n'est pas toujours plus rapide et doit être choisi au cas par cas.
  2. Utilisation appropriée des opérations intermédiaires et des opérations terminales: Les opérations intermédiaires sont évaluées paresseusement et ne sont évaluées que lorsque l'opération terminale est effectuée.
  3. Faites attention à la réutilisabilité de Stream: Une fois qu'un Stream est consommé, il ne peut plus être utilisé. Si vous devez le réutiliser, vous pouvez envisager de convertir le Stream en collection avant de l'utiliser.
  4. Utilisez le bon collecteurCollectorsLa classe propose une variété de collectionneurs et vous pouvez choisir le collectionneur approprié en fonction de vos besoins spécifiques.
  5. Gérer les exceptions: Lorsque vous utilisez l'API Stream, vous devez gérer les exceptions possibles, en particulier dans les opérations sur les fichiers et les opérations sur la base de données.

Foire aux questions et solutions

Le flux est fermé

Une fois qu'un Stream est consommé, il ne peut plus être utilisé. Si vous devez le réutiliser, vous pouvez envisager de convertir le Stream en collection avant de l'utiliser.

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println); // 会抛出IllegalStateException
  • 1
  • 2
  • 3
  • 4

Les problèmes de performance

Les flux parallèles ne sont pas toujours plus rapides que les flux série et doivent être testés au cas par cas.peut utiliserForkJoinPoolPour optimiser les performances du flux parallèle.

ForkJoinPool customThreadPool = new ForkJoinPool(4);
customThreadPool.submit(() ->
    list.parallelStream().forEach(System.out::println)
).get();
  • 1
  • 2
  • 3
  • 4

fuite de mémoire

Lorsque vous utilisez l'API Stream pour traiter de grandes quantités de données, vous devez faire attention au problème des fuites de mémoire.peut utilisercloseméthode pour fermer le Stream, ou utilisertry-with-resourcesL'instruction ferme automatiquement le Stream.

try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {
    lines.forEach(System.out::println);
} catch (IOException e) {
    e.printStackTrace();
}
  • 1
  • 2
  • 3
  • 4
  • 5

Résumer

Cet article présente en détail l'utilisation de l'API Java Stream, y compris les opérations de base, les opérations avancées, le traitement parallèle, les cas pratiques et les meilleures pratiques. En utilisant rationnellement l'API Stream, les développeurs peuvent considérablement simplifier le code, améliorer la lisibilité et la maintenabilité du code, ainsi que l'efficacité du traitement des données. J'espère que cet article vous sera utile pour votre utilisation de l'API Stream dans le développement Java.

L'API Java Stream est un outil puissant pour traiter les données de collecte. Grâce à l'utilisation flexible de diverses opérations, un traitement efficace des données et un calcul en continu peuvent être obtenus. Si vous n'avez pas encore utilisé l'API Stream, il est recommandé d'apprendre et de maîtriser cet outil puissant dès que possible et de l'appliquer à votre projet pour améliorer l'efficacité du développement et la qualité du code.