ejemplo - forEach vs forEachOrdered en Java 8 Stream
java arraylist foreach (3)
Entiendo que estos métodos difieren en el orden de ejecución, pero en todas mis pruebas no puedo lograr una ejecución de orden diferente.
Ejemplo:
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));
Salida:
forEach Demo
Output:AAA
Output:BBB
Output:CCC
forEachOrdered Demo
Output:AAA
Output:BBB
Output:CCC
Proporcione ejemplos cuando 2 métodos produzcan resultados diferentes.
Aunque
forEach
más corto y parece más bonito, sugeriría usar
forEachOrdered
en todos los lugares donde el orden es importante para especificar explícitamente esto.
Para secuencias secuenciales,
forEach
parece respetar el orden e incluso la secuencia de código interno de API
uses
forEach
(para secuencias que se sabe que son secuenciales) donde es semánticamente necesario usar
forEachOrdered
!
Sin embargo, más tarde puede decidir cambiar su transmisión a paralelo y su código se romperá.
Además, cuando utiliza
forEachOrdered
el lector de su código ve el mensaje: "el orden importa aquí".
Por lo tanto, documenta mejor su código.
Tenga en cuenta también que para flujos paralelos,
forEach
no solo se ejecuta en un orden no determinista, sino que también puede ejecutarse simultáneamente en diferentes subprocesos para diferentes elementos (lo que no es posible con
forEachOrdered
).
Finalmente, tanto
forEach
/
forEachOrdered
rara vez son útiles.
En la mayoría de los casos, realmente necesita producir algún resultado, no solo efectos secundarios, por lo tanto, las operaciones como
reduce
o
collect
deberían ser más adecuadas.
Expresar la operación de reducción por naturaleza a través de
forEach
generalmente se considera un mal estilo.
El método forEach () realiza una acción para cada elemento de esta secuencia. Para la transmisión en paralelo, esta operación no garantiza mantener el orden de la transmisión.
El método forEachOrdered () realiza una acción para cada elemento de esta secuencia, garantizando que cada elemento se procese en orden de encuentro para las secuencias que tienen un orden de encuentro definido.
tome el siguiente ejemplo:
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));
Salida:
**** para cada uno sin usar paralelo ****
sushil mittal
**** para cada uno con el uso de paralelo ****
mihul issltat
**** forEachOrdered con el uso de paralelo ****
sushil mittal
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 segunda línea siempre saldrá
Output:AAA
Output:BBB
Output:CCC
mientras que el primero no está garantizado ya que el orden no se mantiene.
forEachOrdered
procesará los elementos de la secuencia en el orden especificado por su fuente, independientemente de si la secuencia es secuencial o paralela.
Citando de
forEach
Javadoc:
El comportamiento de esta operación es explícitamente no determinista. Para las tuberías de flujo paralelo, esta operación no garantiza respetar el orden de encuentro del flujo, ya que al hacerlo se sacrificaría el beneficio del paralelismo.
Cuando el Javadoc
forEachOrdered
establece (el énfasis es mío):
Realiza una acción para cada elemento de esta secuencia, en el orden de encuentro de la secuencia si la secuencia tiene un orden de encuentro definido.