web-dev-qa-db-fra.com

forEach vs forEachOrdered in Java 8 Flux

Je comprends que ces méthodes diffèrent l’ordre d’exécution, mais je ne parviens pas à exécuter différents ordres dans tous les tests.

Exemple:

System.out.println("forEach Demo");
Stream.of("AAA","BBB","CCC").forEach(s->System.out.println("Output:"+s));
System.out.println("forEachOrdered Demo");
Stream.of("AAA","BBB","CCC").forEachOrdered(s->System.out.println("Output:"+s));

Sortie:

forEach Demo
Output:AAA
Output:BBB
Output:CCC
forEachOrdered Demo
Output:AAA
Output:BBB
Output:CCC

Veuillez donner des exemples lorsque 2 méthodes produiront des résultats différents.

65
gstackoverflow
Stream.of("AAA","BBB","CCC").parallel().forEach(s->System.out.println("Output:"+s));
Stream.of("AAA","BBB","CCC").parallel().forEachOrdered(s->System.out.println("Output:"+s));

La deuxième ligne sera toujours sortie

Output:AAA
Output:BBB
Output:CCC

tandis que le premier n'est pas garanti puisque la commande n'est pas conservée. forEachOrdered traitera les éléments du flux dans l'ordre spécifié par sa source, que le flux soit séquentiel ou parallèle.

Citant de forEach Javadoc:

Le comportement de cette opération est explicitement non déterministe. Pour les pipelines à flux parallèles, cette opération ne garantit pas le respect de l'ordre de rencontre du flux, car cela sacrifierait les avantages du parallélisme.

Lorsque le forEachOrdered Javadoc déclare (emphase moi):

Exécute une action pour chaque élément de ce flux, dans l'ordre de rencontre du flux si le flux a un ordre de rencontre défini.

72
Tunaki

Bien que forEach soit plus court et plus joli, je suggérerais d'utiliser forEachOrdered à chaque endroit où l'ordre est important pour le spécifier explicitement. Pour les flux séquentiels, le forEach semble respecter l'ordre et même le code interne de l'API de flux tiliseforEach (pour les flux connus pour être séquentiels) où il est sémantiquement nécessaire de utilisez forEachOrdered! Néanmoins, vous pourrez ultérieurement décider de changer votre flux en parallèle et votre code sera cassé. De plus, lorsque vous utilisez forEachOrdered, le lecteur de votre code voit le message suivant: "l'ordre importe ici". Ainsi, il documente mieux votre code.

Notez également que pour les flux parallèles, forEach n'est pas seulement exécuté dans un ordre non déterministe, mais vous pouvez également le faire exécuter simultanément dans différents threads pour différents éléments (ce qui n'est pas possible avec forEachOrdered).

Enfin, les deux forEach/forEachOrdered sont rarement utiles. Dans la plupart des cas, vous devez réellement produire un résultat, pas seulement un effet secondaire. Par conséquent, des opérations comme reduce ou collect devraient être plus appropriées. Exprimer une opération de réduction par nature via forEach est généralement considéré comme un mauvais style.

27
Tagir Valeev

forEach () met en œuvre une action pour chaque élément de ce flux. Pour les flux parallèles, cette opération ne garantit pas le maintien de l'ordre du flux.

forEachOrdered () met en œuvre une action pour chaque élément de ce flux, garantissant que chaque élément est traité dans l'ordre de la recherche pour les flux ayant un ordre de consultation défini.

prendre ci-dessous exemple:

    String str = "sushil mittal";
    System.out.println("****forEach without using parallel****");
    str.chars().forEach(s -> System.out.print((char) s));
    System.out.println("\n****forEach with using parallel****");

    str.chars().parallel().forEach(s -> System.out.print((char) s));
    System.out.println("\n****forEachOrdered with using parallel****");

    str.chars().parallel().forEachOrdered(s -> System.out.print((char) s));

Sortie:

**** pourChaque sans utiliser parallèle ****

sushil mittal

**** pour chaque utilisation avec parallèle ****

mihul issltat

**** forEachOrdered with using parallel ****

sushil mittal

10
Sushil Mittal