forEach vs forEachOrdered en Java 8 Stream

Entiendo que estos métodos difieren en el orden de ejecución, pero en toda mi prueba 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.

 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 dará salida

 Output:AAA Output:BBB Output:CCC 

mientras que el primero no está garantizado ya que el orden no se cumple. forEachOrdered procesará los elementos de la secuencia en el orden especificado por su origen, independientemente de si la secuencia es secuencial o paralela.

Citando de para 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 de la secuencia, ya que al hacerlo, se sacrificaría el beneficio del paralelismo.

Cuando los estados de Javadoc forEachOrdered (énfasis mío):

Realiza una acción para cada elemento de esta secuencia, en el orden de encuentro de la secuencia si la secuencia tiene una orden de encuentro definida.

Aunque forEach cada forEach más corto y se ve más bonito, sugiero usar forEachOrdered en cada lugar donde el orden importa para especificar esto de manera explícita. Para las secuencias secuenciales, forEach parece respetar el orden e incluso el código interno de la API de transmisión usa forEach (para la secuencia que se sabe que es secuencial) donde es semánticamente necesario usar forEachOrdered . Sin embargo, más tarde puede decidir cambiar su flujo a paralelo y su código se romperá. Además, cuando usa forEachOrdered el lector de su código ve el mensaje: “el pedido importa aquí”. Por lo tanto, documenta su código mejor.

Tenga en cuenta también que para las transmisiones paralelas, forEach no solo se ejecuta en un orden no determinista, sino que también se puede ejecutar simultáneamente en diferentes subprocesos para diferentes elementos (lo que no es posible con forEachOrdered ).

Finalmente ambos forEach / forEachOrdered raramente son útiles. En la mayoría de los casos, en realidad necesitas producir algún resultado, no solo efecto secundario, 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 cada forEach generalmente se considera como un mal estilo.

El método forEach () realiza una acción para cada elemento de esta secuencia. Para 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, lo que garantiza que cada elemento se procesa en orden de encuentro para las secuencias que tienen una orden de encuentro definida.

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 paralelo ****

mihul issltat

**** forEachOrdered con el uso paralelo ****

sushil mittal