java java-8 java-stream

java - Cuales operaciones conservan orden



java-8 java-stream (2)

Después de algunas investigaciones en el código fuente, resumí las siguientes tablas:

Tomado de: flujos de Java - Parte 6 - Spliterator

La siguiente tabla muestra los tipos de operaciones que pueden modificar las características de caracteres:

| | DISTICTS | SORTED | ORDERED | SIZED | SHORT_CIRCUIT | | ---------------------- | -------- | ------ | ------- | ----- | --------------| | source stream | Y | Y | Y | Y | N | | intermediate operation | PCI | PCI | PCI | PC | PI | | terminal operation | N | N | PC | N | PI |

  • Y - Permitido tener
  • P - Conservas de mayo
  • C - mayo despeja.
  • I - Puede inyectar.
  • N - No es válido; Irelevant para la operación.

Tomado de flujos de Java - tabla de características de métodos de flujo

La siguiente tabla muestra qué características y banderas pueden SHORT_CIRCUIT y desactivarse cada operación intermedia / terminal : ( SHORT_CIRCUIT es relevante solo en el contexto de StreamOpFlag banderas StreamOpFlag )

Nota: la bandera P (Conservar) se agrega a cada celda, excepto las que tienen las banderas C e I (Borrar e Inyectar).

| | DISTINCT | SORTED | ORDERED | SIZED | SHORT_CIRCUIT | | ---------------- | ----------| --------| ---------| -------| ---------------| | filter | | | | C | | | forEach | | | C | | | | forEachOrdered | | | | | | | allMatch | | | C | | I | | distinct | I | | | C | | | flatMap | C | C | | C | | | anyMatch | | | C | | I | | collect | | | | | | | unOrdered | | | C | | | | count | C | C | C | C | | | findAny | | | C | | I | | findFirst | | | | | I | | flatMapToXXX | C | C | | C | | | limit | | | | C | I | | map | C | C | | | | | mapToXXX | C | C | | | | | max | | | | | | | min | | | | | | | noneMatch | | | C | | I | | peek | | | | | | | reduce | | | | | | | skip | | | C | I | | | sorted | | I | I | | | | toArray | | | | | |

  • C - Despeja.
  • I - Inyecta.

Esta pregunta ya tiene una respuesta aquí:

TL; DR; Estoy buscando un lugar donde pueda buscar si una determinada operación intermedia o terminal. ¿Dónde puedo encontrar dicha documentación?

Editar ¿ Esto no es un duplicado de Cómo garantizar el orden de procesamiento en las secuencias java8? , ya que esa pregunta no proporciona una lista completa de las operaciones.

Fondo

La documentación del paquete dice:

Si una secuencia tiene o no un orden de encuentro depende de la fuente y las operaciones intermedias

Lo cual se repite en esta excelente respuesta de stackoverflow.

Para garantizar el mantenimiento del pedido a lo largo de toda una operación de flujo, debe estudiar la documentación de la fuente del flujo, todas las operaciones intermedias y la operación del terminal para saber si mantienen el pedido o no (o si la fuente tiene un pedido en la primera lugar).

Eso está muy bien, pero ¿qué documentación debo ver? La documentación del paquete menciona en un ejemplo que el map garantiza el orden, pero no tiene una lista exhaustiva. El javadoc para la clase Stream documenta algunas operaciones intermedias, pero no todas. Tomemos por ejemplo el map :

Devuelve un flujo que consiste en los resultados de aplicar la función dada a los elementos de este flujo.

Esta es una operación intermedia.

o filter

Devuelve una secuencia que consta de los elementos de esta secuencia que coinciden con el predicado dado.

Esta es una operación intermedia.

Ninguno de estos describe si conservan el orden.

Esta respuesta de stackoverflow reclama:

En realidad, cada operación intermedia conserva un pedido por defecto. Las únicas excepciones son:

  • unordered () que elimina la restricción de ordenación.
  • ordenado () que cambia el orden.

Cuando no se especifica explícitamente, puede asumir que la operación mantiene el orden. Incluso distinct () mantiene el orden, aunque agrega mucha complejidad para la transmisión en paralelo.

¿Pero hay alguna documentación oficial que respalde eso?

Crédito extra 😉

El en realidad tiene dos problemas de pedido por separado.

  1. ¿La salida de la operación mantiene el mismo orden que la entrada?
  2. Es la operación ejecutada en orden en cada elemento.

Por ejemplo, una operación de map paralelo podría repasar todos los elementos en un orden arbitrario (violando 2.), pero aún así mantener el orden en el flujo devuelto (obedeciendo a 1.)


Parece una especie de dos duplicados, ya que las respuestas que vinculaste realmente explican las cosas. No puedo decir si el map o el filter deben decir específicamente que conservan el orden; no se basan en ningún estado anterior ni en ningún otro estado (estas son operaciones sin estado), por lo que está implícito que conservan el orden por lo que puedo ver. Lo veo al revés, si no conservan el orden, eso debería mencionarse explícitamente en los documentos; Si no es obvio a partir del nombre de la operación. Por ejemplo, Stream.generate no es obvio para mí si generó una secuencia ordenada; Así se dice esto en la documentación de la misma:

Devuelve una secuencia desordenada secuencial infinita donde cada elemento es generado por el Proveedor proporcionado.

sorted y unordered por otro lado, son bastante obvios (IMO) para cambiar el orden, al menos cuando los colocas, estás diciendo explícitamente que no te importa el pedido. unordered BTW no realizará aleatorizaciones con el propósito de satisfacer esto, puede leer más here .

Hay dos órdenes en general: orden de procesamiento y orden de encuentro .

Puede pensar en el orden de encuentro como un procesamiento de izquierda a derecha (imagine que tiene una List o una array ). Por lo tanto, si tiene una tubería que no cambia el orden, los elementos se enviarán al Collector (o cualquier otra operación del terminal) como se ve de izquierda a derecha. Bueno, no todas las operaciones de la terminal son así. Una diferencia obvia es para cada forEach y para cada forEachOrdered ; o un Collectors.toSet , que no necesita conservar el orden inicial en absoluto. O tomemos findAny como la operación de la terminal; obviamente, no te importa qué elemento quieres, así que, ¿por qué molestarse en findAny al findAny en el orden exacto en primer lugar?

Por otro lado, el orden de procesamiento no tiene un orden definido, especialmente visible para el procesamiento paralelo, obviamente. Por lo tanto, incluso si su canalización es paralela (y los elementos se procesan sin ninguna garantía de ningún orden), se enviarán a la operación del terminal en orden, si tal orden es necesaria para dicha operación.