Rozumiem, że te metody różnią się kolejnością wykonywania, ale we wszystkich moich testach nie mogę osiągnąć innej realizacji zamówienia.
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));
Wynik:
forEach Demo
Output:AAA
Output:BBB
Output:CCC
forEachOrdered Demo
Output:AAA
Output:BBB
Output:CCC
Proszę podać przykłady, kiedy 2 metody dadzą różne wyniki.
java
foreach
java-8
java-stream
gstackoverflow
źródło
źródło
Odpowiedzi:
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 będzie wyświetlana
podczas gdy pierwsza nie jest gwarantowana, ponieważ zamówienie nie jest dotrzymywane.
forEachOrdered
przetwarza elementy strumienia w kolejności określonej przez źródło, niezależnie od tego, czy strumień jest sekwencyjny czy równoległy.Cytat z
forEach
Javadoc:Kiedy
forEachOrdered
Javadoc stwierdza (podkreślenie moje):źródło
forEachOrdered
zparallel
?Chociaż jest
forEach
krótszy i wygląda ładniej, sugerowałbym użycie goforEachOrdered
w każdym miejscu, w którym ma znaczenie, aby wyraźnie to określić. W przypadku strumieni sekwencyjnychforEach
wydaje się, że szanuje kolejność, a nawet wykorzystuje wewnętrzny kod API strumieniaforEach
(dla strumienia, o którym wiadomo, że jest sekwencyjny), gdzie jest to semantycznie konieczneforEachOrdered
! Niemniej jednak możesz później zdecydować się na zmianę strumienia na równoległy, a kod zostanie uszkodzony. Również podczas korzystaniaforEachOrdered
z czytnika Twojego kodu zobaczysz komunikat: „tu liczy się kolejność”. W ten sposób lepiej dokumentuje twój kod.Należy również zauważyć, że dla strumieni równoległych
forEach
nie tylko jest wykonywany w kolejności niedetenistycznej, ale można go również wykonywać jednocześnie w różnych wątkach dla różnych elementów (co nie jest możliwe w przypadkuforEachOrdered
).Wreszcie oba
forEach
/forEachOrdered
są rzadko przydatne. W większości przypadków faktycznie potrzebujesz jakiegoś wyniku, a nie tylko efektu ubocznego, dlatego operacje takie jakreduce
lubcollect
powinny być bardziej odpowiednie. Wyrażanie operacji redukcji z natury za pomocąforEach
jest zwykle uważane za zły styl.źródło
forEachOrdered
w tym kodzie jest semantycznie konieczne ?flatMap
). Można go zamówić, więc należy go umieścić w otrzymanym strumieniu w tej samej kolejności.Stream.of("a", "b", "c").flatMap(s -> Stream.of("1", "2", "3").map(s::concat)).spliterator().hasCharacteristics(Spliterator.ORDERED)
zwraca wartość true, dlatego należy określić kolejność wynikowego strumienia. Jeśli uważasz, że dokumentacja JDK powinna wyraźnie o tym mówić, możesz zgłosić błąd.forEach()
wykonuje akcję dla każdego elementu tego strumienia. W przypadku strumienia równoległego ta operacja nie gwarantuje utrzymania kolejności strumienia.forEachOrdered()
metoda wykonuje akcję dla każdego elementu tego strumienia, gwarantując, że każdy element jest przetwarzany w kolejności napotkania dla strumieni, które mają zdefiniowaną kolejność spotkań.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));
Wynik:
źródło