web-dev-qa-db-fra.com

Méthode Stream.peek () dans Java 8 vs Java 9

Je suis en train d'apprendre par Java 8 expressions lambda et voudrais poser des questions sur le code suivant Java le code relatif au peek dans l'interface de fonction que j'ai rencontrée.

Lors de l'exécution du programme sur IDE, cela ne donne aucune sortie. Je m'attendais à ce que cela donne 2, 4, 6.

import Java.util.Arrays;
import Java.util.List;

public class Test_Q3 {

    public Test_Q3() {
    }

    public static void main(String[] args) {
        List<Integer> values = Arrays.asList(1, 2, 3);
        values.stream()
              .map(n -> n * 2)
              .peek(System.out::print)
              .count();
    }
}
65
Patrick C.

Je suppose que vous utilisez ceci sous Java 9? Vous ne modifiez pas la propriété SIZED du flux, il n’est donc pas nécessaire d’exécuter map ou peek du tout.

En d’autres termes, tout ce qui vous intéresse concerne le résultat final, count, mais vous ne modifiez pas pour autant la taille initiale du List dans aucun (via filter par exemple ou distinct) Il s'agit d'une optimisation effectuée dans les flux.

Au fait, même si vous ajoutez un filtre factice, cela montrera ce que vous attendez:

values.stream ()
      .map(n -> n*2)
      .peek(System.out::print)
      .filter(x -> true)
      .count();
60
Eugene

Voici quelques citations pertinentes de la Javadoc de l'interface Stream :

Une implémentation en flux est autorisée une latitude importante dans l'optimisation du calcul du résultat. Par exemple, une implémentation de flux est libre d'éluder des opérations (ou d'étapes entières) d'un pipeline de flux - et donc d'élire l'invocation de paramètres comportementaux - si elle peut prouver que cela n'affectera pas la résultat du calcul . Cela signifie que les effets secondaires des paramètres comportementaux ne peuvent pas toujours être exécutés et ne doivent pas être invoqués, sauf indication contraire (par exemple, dans les opérations de terminal forEach). et pour chaque ordre). (Pour un exemple spécifique d'une telle optimisation, voir la note d'API documentée sur l'opération count (). Pour plus de détails, voir la section sur les effets secondaires de la documentation du paquet de flux.)

Et plus précisément de la Javadoc de count () méthode:

Note de l'API:

Une implémentation peut choisir de ne pas exécuter le pipeline (de manière séquentielle ou parallèle) si elle est capable de calculer le nombre directement à partir de la source de flux . Dans ce cas, aucun élément source ne sera traversé et aucune opération intermédiaire ne sera évaluée . Les paramètres comportementaux ayant des effets secondaires, fortement déconseillés, sauf dans des cas inoffensifs tels que le débogage, peuvent être affectés. Par exemple, considérons le flux suivant:

List<String> l = Arrays.asList("A", "B", "C", "D");
long count = l.stream().peek(System.out::println).count();

Le nombre d'éléments couverts par la source de flux, une liste, est connu et l'opération intermédiaire, peek, n'injecte ni ne supprime d'éléments dans le flux (comme cela peut être le cas pour les opérations flatMap ou filter). Ainsi, le nombre correspond à la taille de la liste et il n’est pas nécessaire d’exécuter le pipeline et, indirectement, d’imprimer les éléments de la liste.

Ces guillemets n'apparaissent que sur le Javadoc de Java 9, il doit donc s'agir d'une nouvelle optimisation.

58
Eran