forEach vs foreach w Javie 8 Stream

Rozumiem, że te metody różnią się kolejnością wykonania, ale w całym moim teście nie mogę osiągnąć innego wykonania zlecenia.

Przykład:

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));

Wyjście:

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

Proszę podać przykłady, gdy 2 metody przyniosą różne wyniki.

Author: Tunaki, 2015-09-26

3 answers

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));

Druga linia zawsze wyświetli

Output:AAA
Output:BBB
Output:CCC

Podczas gdy pierwsza nie jest gwarantowana, ponieważ zamówienie nie jest utrzymywane. forEachOrdered przetwarza elementy strumienia w kolejności określonej przez jego źródło, niezależnie od tego, czy strumień jest sekwencyjny czy równoległy.

Cytowanie z forEach Javadoc:

Zachowanie tej operacji jest jawnie nieeterministyczne. W przypadku rurociągów o równoległym strumieniu operacja ta nie gwarantuje przestrzegania spotkać się z porządkiem strumienia, gdyż uczynienie tego poświęciłoby korzyść paralelizmu.

Gdy forEachOrdered Stany Javadoc (podkreślenie):

Wykonuje akcję dla każdego elementu tego strumienia, w porządku spotkania strumienia jeśli strumień ma zdefiniowany porządek spotkania.

 54
Author: Tunaki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-26 13:18:29

Chociaż forEach jest krótszy i wygląda ładniej, sugerowałbym użycie forEachOrdered w każdym miejscu, gdzie liczy się porządek, aby to wyraźnie określić. Dla sekwencyjnych strumieni forEach wydaje się, że respektuje kolejność, a nawet wewnętrzny kod stream API używa forEach (dla strumienia, który jest znany jako sekwencyjny), gdzie semantycznie konieczne jest użycie forEachOrdered! Niemniej jednak możesz później zdecydować się na zmianę strumienia na równoległy, a Twój kod zostanie uszkodzony. Również gdy używasz forEachOrdered czytnika kodu widzi komunikat: "tu liczy się porządek". W ten sposób lepiej dokumentuje Twój kod.

Zauważ również, że dla równoległych strumieni forEach nie tylko jest wykonywany w porządku niedetermenistycznym, ale także może być wykonywany jednocześnie w różnych wątkach dla różnych elementów(co nie jest możliwe w przypadku forEachOrdered).

Wreszcie oba forEach/forEachOrdered są rzadko przydatne. W większości przypadków rzeczywiście trzeba uzyskać jakiś wynik, a nie tylko efekt uboczny, a więc operacje takie jak reduce lub collect powinno być bardziej odpowiednie. Wyrażanie operacji redukcji przez naturę za pomocą forEach jest zwykle uważane za zły styl.

 22
Author: Tagir Valeev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-26 13:31:28

Metoda ForEach () wykonuje akcję dla każdego elementu tego strumienia. W przypadku równoległego strumienia operacja ta nie gwarantuje utrzymania porządku strumienia.

Metoda ForEachOrdered() wykonuje akcję dla każdego elementu tego strumienia, gwarantując, że każdy element jest przetwarzany w porządku spotkania dla strumieni, które mają zdefiniowany porządek spotkania.

Weźmy poniższy przykład:

    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));

Wyjście:

****forEach bez użycia parallel * * * *

Sushil mittal

****forEach with using parallel * * * *

Mihul issltat

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

Sushil mittal

 0
Author: Sushil Mittal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-26 06:59:03