streams recorrer procesamiento parte metodos lista ejemplo datos con java java-8 java-stream

procesamiento - recorrer lista java 8



¿Stream.forEach respeta el orden de encuentro de las secuencias secuenciales? (1)

El Javadoc para Stream.forEach dice (el énfasis es mío):

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. Para cualquier elemento dado, la acción se puede realizar en cualquier momento y en cualquier hilo que elija la biblioteca. Si la acción accede al estado compartido, es responsable de proporcionar la sincronización requerida.

El mismo texto está presente en Javadoc Early Access Javadoc .

La primera oración ("explícitamente no determinista") sugiere (pero no dice explícitamente) que este método no preserva el orden de encuentro. Pero la siguiente oración, que dice explícitamente que el orden no se conserva, está condicionada a "Para tuberías de flujo paralelo", y esa condición sería innecesaria si la oración se aplicara independientemente del paralelismo. Eso me deja inseguro de si cada uno conserva el orden de encuentro para las secuencias secuenciales.

Esta respuesta señala un lugar donde la implementación de la biblioteca de secuencias llama a .sequential().forEach(downstream) . Eso sugiere que forEach está destinado a preservar el orden de las secuencias secuenciales, pero también podría ser un error en la biblioteca.

He eludido esta ambigüedad en mi propio código al usar forEachOrdered para estar en el lado seguro, pero hoy descubrí que la sugerencia del editor "usar operaciones funcionales" de NetBeans IDE convertirá

for (Foo foo : collection) foo.bar();

dentro

collection.stream().forEach((foo) -> { foo.bar(); });

que introduce un error si forEach no conserva el orden de encuentro. Antes de informar un error contra NetBeans , quiero saber qué garantiza realmente la biblioteca, respaldada por una fuente.

Estoy buscando una respuesta basada en fuentes autorizadas . Eso podría ser un comentario explícito en la implementación de la biblioteca, una discusión sobre las listas de correo de desarrollo de Java (Google no encontró nada para mí, pero tal vez no sé las palabras mágicas), o una declaración de los diseñadores de la biblioteca (de la cual los dos, Brian Goetz y Stuart Marks , están activos en Stack Overflow). (Por favor, no responda con "solo use forEachOrdered en su lugar", ya lo hago, pero quiero saber si el código que no está mal).


Existen especificaciones para describir las garantías mínimas de las que puede depender la persona que llama, no para describir lo que hace la implementación. Esta brecha es crucial, ya que permite que la flexibilidad de implementación evolucione. (La especificación es declarativa; la implementación es imperativa). La sobreespecificación es tan mala como la subespecificación.

Cuando una especificación dice "no conserva la propiedad X", no significa que la propiedad X nunca se pueda observar; significa que la implementación no está obligada a preservarla. Su supuesta implicación de que el orden del encuentro nunca se preserva es simplemente una conclusión incorrecta. ( HashSet no promete que iterar sus elementos conserva el orden en que se insertaron, pero eso no significa que esto no pueda suceder accidentalmente, simplemente no puede contar con eso).

Del mismo modo, su implicación de "eso sugiere que cada uno tiene la intención de preservar el orden de las secuencias secuenciales" porque vio que una implementación que lo hace en algunos casos es igualmente incorrecta.

En ambos casos, parece que te sientes incómodo con el hecho de que la especificación otorga a cada forEach una gran libertad. Específicamente, tiene la libertad de no preservar el orden de encuentro para las secuencias secuenciales, aunque eso es lo que hace actualmente la implementación, y además es difícil imaginar que una implementación se salga de su camino para procesar fuentes secuenciales fuera de servicio. Pero eso es lo que dice la especificación, y eso es lo que estaba destinado a decir.

Dicho esto, la redacción del comentario sobre flujos paralelos es potencialmente confusa, porque todavía es posible malinterpretarla. La intención de llamar explícitamente el caso paralelo aquí era pedagógica; la especificación sigue siendo perfectamente clara con esa oración eliminada por completo. Sin embargo, para un lector que desconoce el paralelismo, sería casi imposible no asumir que cada forEach preservaría el orden del encuentro, por lo que se agregó esta oración para ayudar a aclarar la motivación. Pero, como usted señala, el deseo de tratar el caso secuencial especialmente sigue siendo tan poderoso que sería beneficioso aclararlo más.