[java8] Pour comprendre l'API Stream

Cela fait 4 mois que j'ai changé de poste en ingénieur sans expérience et a été affecté à l'équipe java. Je suis déjà habitué à java, mais j'utilise l'instruction Extended for pour développer la liste. Je veux m'entendre avec Stream API, alors je l'ai résumé.

Nous prévoyons d'ajouter des méthodes au besoin.

Qu'est-ce que l'API Stream?

Aperçu

Pour commencer, je pense qu'il est bon d'avoir une impression de "** quelque chose qui permet de faire fonctionner facilement le tableau **". L'évaluation des délais et le traitement asynchrone sont décrits ci-dessous, mais vous n'avez pas besoin de le savoir au début. (Je ne comprends pas grand-chose, donc je veux le penser ..)

Fonctionnalités de l'API Stream

Stream peut faire fonctionner des tableaux avec une petite quantité de description et a les fonctions suivantes.

Traitement asynchrone

L'API Stream peut effectuer le traitement asynchrone. Le traitement asynchrone, comme son nom l'indique, n'exécute pas une série de processus séquentiellement (synchronisation), mais les exécute en parallèle (asynchrone). Pour un traitement asynchrone avec l'API Stream, utilisez list.parallelStream () ou List.stream (). Parallel () au lieu de l'habituel List.stream ().

Par exemple, s'il existe un processus pour afficher les éléments de liste suivants à l'écran,

List<Integer> demoList = Arrays.asList(1, 2, 3, 4, 5);

Si vous le faites de manière synchrone, la sortie sera dans l'ordre du tableau car elle sera exécutée séquentiellement.

    for(Integer i : demoList) {
      System.out.print(i);
    }
    // 12345

Cependant, si vous le faites de manière asynchrone, il sera traité en parallèle, de sorte que la sortie sera différente de l'ordre du tableau.

    demoList.stream().parallel().forEach(System.out::print);
    // 32415

En outre, en effectuant un traitement asynchrone, le traitement peut être effectué plus rapidement que la rotation de la liste avec For. J'ai en fait mesuré le temps.


    //Liste des cibles
    List<Integer> demoList = Stream.iterate(1, n -> n + 1).limit(100000).collect(Collectors.toList());

    //Pour obtenir le temps avant le traitement
    long startTimeFor = System.currentTimeMillis();

    //Sortie avec For
    for(Integer i : demoList) {
      System.out.println(i);;
    }

    //Obtenez le temps après pour le traitement
    long endTimeFor = System.currentTimeMillis();

    //Obtenez l'heure avant le traitement du flux
    long startTimeStream = System.currentTimeMillis();
    
    //Sortie avec Stream
    demoList.parallelStream().forEach(System.out::println);

    //Obtenez l'heure après le traitement du flux
    long endTimeStream = System.currentTimeMillis();

    System.out.println("Temps de traitement pour:" + (endTimeFor - startTimeFor) + " ms");
    System.out.println("Temps de traitement Stream:" + (endTimeStream - startTimeStream) + " ms");

Les résultats sont les suivants. Ce n'est pas aussi différent que je m'y attendais, mais le processus ci-dessus était environ 100 ms plus rapide en moyenne.

Temps de traitement pour: 686 ms
Temps de traitement Stream: 573 ms

Évaluation des retards

L'API Stream peut effectuer une évaluation de retard des langages fonctionnels. Qu'est-ce que l'évaluation des retards?

En programmation, les formules sont souvent calculées lorsqu'elles apparaissent, mais retarder l'évaluation consiste à ne pas les calculer jusqu'à ce qu'elles soient réellement nécessaires.

Il est. Dans StreamAPI, les expressions ne sont pas évaluées lors des opérations intermédiaires (carte et filtre) décrites plus loin. Il n'est évalué que lorsque l'opération de terminaison est effectuée. Déplaçons-le et vérifions-le.

    //Liste des cibles
    List<Integer> demoList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));

    //Seuls les nombres pairs sont diffusés. Comme il s'agit d'un processus intermédiaire, il n'a pas encore été évalué.
    Stream<Integer> oddListStream = demoList.stream().filter(n -> n % 2 == 0);

    //Ajouter un élément à demoList
    demoList.add(6);
    demoList.add(7);
    demoList.add(8);

    //Flux de sortie
    oddListStream.forEach(System.out::print);

Si vous y pensez normalement, le oddListStream qui génère le Stream doit contenir 2 et 4. Cependant, les opérations intermédiaires de Stream sont différées et ne sont pas évaluées jusqu'à ce que l'opération de terminaison forEach soit appelée. Donc, la sortie est ...

$  2468

Et, 6,7,8 ajouté à demoList après le traitement de la génération Stream.

Flux de processus

À partir de là, nous allons examiner l'opération Stream dans l'ordre de génération → opération intermédiaire → opération de terminaison.

1. Génération de flux

Tout d'abord, créez un Stream qui servira de base à l'exécution des opérations décrites ci-dessous. En plus de List.stream () couramment utilisé, Stream a diverses méthodes telles que l'utilisation d'un constructeur et l'utilisation d'un générateur.

    //À partir du type de liste
    Stream<Integer> numberStreamFromList = Arrays.asList(8, 1, 4, 2, 9).stream();

    // Stream.avec de
    Stream<Integer> numberStreamFromStreamOf = Stream.of(8, 1, 4, 2, 9);

    //Utilisation du constructeur
    Builder<String> builder = Stream.builder();
    Stream<String> stringStream = builder.add("hoge").add("fuga").build();

    //Flux vide
    Stream<String> emptyStream = Stream.empty();

    //Avec iterate
    Stream<Integer> numberStreamFromIterate = Stream.iterate(1, n -> n * 10).limit(5);

Seule la méthode d'utilisation de l'itération est un peu difficile à comprendre, c'est donc un supplément. La syntaxe de base est la suivante.

Stream.iterate(valeur initiale, valeur initialeが入る変数 ->Traitement des variables).limit(Nombre de répétitions)

La raison de l'application de la limite est que si la limite n'est pas utilisée, elle sera générée indéfiniment.

Vous pouvez facilement faire cette sortie avec iterate.

Dites un nombre à partir de 1 et ne devenez stupide que s'il s'agit d'un multiple de 3 (ressentez les temps ..)

    Stream.iterate(1, n -> n + 1).limit(100)
        .map(n -> n % 3 == 0 ? "Stupide" : n)
        .forEach(System.out::println);

2. Fonctionnement intermédiaire

L'opération intermédiaire consiste à effectuer des traitements tels que le filtrage et l'exécution de fonctions pour chaque élément du tableau. L'opération intermédiaire peut être répétée plusieurs fois. Après filtrage, traiter avec la carte, etc. Veuillez noter que la valeur de retour de l'opération intermédiaire sera de type stream . Il ne renvoie pas de tableau dans list.map comme ruby. Afin de le rendre différent du type stream , l'opération de terminaison décrite plus loin est requise.

Sélection d'élément [filtre]

Vous pouvez * filtrer * des éléments sous certaines conditions en utilisant filter (). Voici un exemple d'utilisation.

Sortie uniquement des nombres pairs du tableau

    //Liste des cibles
    List<Integer> numberList = Arrays.asList(8, 1, 4, 2, 9);

    //Sortie uniquement même pour déclaration
    for (Integer number : numberList) {
      if (number % 2 == 0) {
        System.out.println(number);
      }
    }

    //Sortie uniquement des nombres pairs Stream
    numberList.stream()
        .filter(n -> n % 2 == 0)
        .forEach(System.out::println);

Modifier l'élément [carte]

Double chaque élément du tableau et le produit

    List<Integer> numberList = Arrays.asList(8, 1, 4, 2, 9);

    //Sortie en doublant chaque élément pour l'instruction
    for (Integer number : numberList) {
      System.out.println(number * 2);
    }

    //Double chaque élément pour le flux de sortie
    numberList.stream()
        .map(n -> n * 2)
        .forEach(System.out::println);

Tri des éléments [sort]

Le tri des éléments est facile avec le tri.

    List<Integer> numberList = Arrays.asList(8, 1, 4, 2, 9);

    List<Integer> sortListAsc = numberList.stream().sorted().collect(Collectors.toList());

    List<Integer> sortListDesc = numberList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

    System.out.println(sortListAsc);
    // [1, 2, 4, 8, 9]

    System.out.println(sortListDesc);
    // [9, 8, 4, 2, 1]

3. Opération de terminaison

Pour l'opération de terminaison, vous pouvez exécuter la fonction de manière séquentielle à l'aide du flux traité par mappage, filtre, etc., ou le convertir dans le type spécifié. La différence avec l'opération intermédiaire est que la valeur de retour n'est pas Stream.

Voici un exemple typique.

Recevoir le résultat dans le type spécifié [collect]

Vous pouvez utiliser collect pour convertir un Stream en différents types et obtenir le résultat.

Recevoir sous forme de tableau [Collectors.toList ()]

Doublez l'élément et recevez le résultat sous forme de tableau

    List<Integer> numberList = Arrays.asList(8, 1, 4, 2, 9);

    List<Integer> doubleList = numberList.stream()
        .map(n -> n * 2)
        .collect(Collectors.toList());

    System.out.println(doubleList); //[16, 2, 8, 4, 18]

Recevoir sur la carte [Collectors.toMap ()]

Jugez la valeur et créez une carte appelée [valeur, "paire" ou "impaire"].

    List<Integer> numberList = Arrays.asList(8, 1, 4, 2, 9);

    Map<Integer, String> demoMap  = numberList.stream()
        .collect(Collectors.toMap(
            n -> n,
            s -> s % 2 == 0 ? "Même" : "Impair"));

    System.out.println(demoMap); //{1=Impair, 2=Même, 4=Même, 8=Même, 9=Impair}

Traiter chaque élément [forEach]

Sortie standard telle quelle

    List<Integer> numberList = Arrays.asList(8, 1, 4, 2, 9);

    //Les deux sont les mêmes
    numberList.stream().forEach(n -> System.out.println(n));
    numberList.stream().forEach(System.out::println);

référence

http://www.task-notes.com/entry/20150518/1431918000 https://qiita.com/nmby/items/52d1b0e2dad5df475737 http://aoking.hatenablog.jp/entry/20110810/1312970979 https://qiita.com/kumazo/items/104fa685da8705b8cfd8#36-flatmap

Recommended Posts

[java8] Pour comprendre l'API Stream
[Java] Introduction à l'API Stream
[Introduction à Java] À propos de l'API Stream
API Java Stream
Java 8 ~ Stream API ~ pour commencer maintenant
Référence Java à comprendre dans la figure
Essayez d'utiliser l'API Stream en Java
J'ai essayé de résumer l'API Stream
[Java] API / carte de flux
Pratique de l'API Java8 Stream
Aide-mémoire de l'API Java Stream
API Java Stream en 5 minutes
[Java] Stream API - Traitement de l'arrêt du flux
[Java] Stream API - Traitement intermédiaire de flux
Thread Java pour comprendre vaguement
[Java] Opération intermédiaire de l'API Stream
Entrée dans la console Java
[Pour les débutants] Comment utiliser Stream API après Java 8
Utiliser des expressions Java lambda en dehors de l'API Stream
Classes et instances Java comprises dans la figure
Java: utilisez Stream pour trier le contenu d'une collection
[À voir absolument pour l'apprenti ingénieur Java] Comment utiliser l'API Stream
Je souhaite utiliser l'API Java 8 DateTime lentement (maintenant)
J'ai essayé d'utiliser l'API Java8 Stream
Bienvenue dans le marais des bibliothèques Java! !!
Analyser l'analyse syntaxique de l'API COTOHA en Java
Traitement des listes à comprendre avec des images --java8 stream / javaslang --bonus
Il est maintenant temps de commencer avec l'API Stream
La route de JavaScript à Java
Convertir un tableau bidimensionnel au format csv avec l'API Java 8 Stream
Comment lire un fichier MIDI à l'aide de l'API Java Sound
Exemple de code pour appeler l'API Yahoo! Local Search en Java
Tirez parti de l'un ou l'autre pour la gestion des exceptions individuelles dans l'API Java Stream
[Java] Comment utiliser la classe File
Traitement des données à l'aide de l'API de flux de Java 8
Introduction à Java pour la première fois # 2
Appelez l'API de notification Windows en Java
Java SE8 Silver ~ La route à franchir ~
De nos jours, les expressions Java Lambda et l'API de flux
À propos de la procédure pour que Java fonctionne
[Java] Comment utiliser la méthode toString ()
Accédez à l'API REST Salesforce depuis Java
Etudier comment utiliser le constructeur (java)
[Traitement × Java] Comment utiliser la boucle
[Java] Comment régler la date sur 00:00:00
Essayez différentes méthodes d'API Java Stream (maintenant)
[Java] Comment obtenir le répertoire actuel
Java 8 pour démarrer maintenant ~ API de date et d'heure ~
[Java] Map # merge est difficile à comprendre.
L'API de sécurité Java EE est là!
[Traitement × Java] Comment utiliser la classe
Classe anonyme (visant à introduire l'API de flux)
Comment obtenir la date avec Java
Sortie du livre "Introduction à Java"
[Traitement × Java] Comment utiliser la fonction
Je suis allé au Java Women's Club # 1