print parallel maptoint intstream example java java-8 java-stream short-circuiting

parallel - stream interface java doc



Corto circuito en Java 8 (5)

Al leer un poco sobre Java 8, llegué a this publicación del blog explicando un poco acerca de las transmisiones y la reducción de ellas, y cuándo sería posible provocar un cortocircuito en la reducción. En la parte inferior dice:

Tenga en cuenta que en el caso de findFirst o findAny solo necesitamos el primer valor que coincida con el predicado (aunque findAny no está garantizado para devolver el primero). Sin embargo, si la transmisión no tiene orden, entonces esperamos que findFirst comporte como findAny . Es posible que las operaciones allMatch , noneMatch y anyMatch no anyMatch cortocircuitos en el flujo, ya que puede tomar evaluar todos los valores para determinar si el operador es true o false . Por lo tanto, una corriente infinita que usa estos puede no terminar.

Obtengo que findFirst o findAny puede findAny un cortocircuito en la reducción, porque tan pronto como encuentre un elemento, no necesita procesar más.

Pero, ¿por qué esto no sería posible para allMatch , noneMatch y anyMatch ? Para allMatch , si encuentra uno que no coincide con el predicado, puede detener el procesamiento. Lo mismo para ninguno. ¿Y cualquier anyMatch especial no tiene sentido para mí, ya que es prácticamente igual a findAny a findAny (excepto por lo que se devuelve)?

Decir que estos tres pueden no provocar un cortocircuito, ya que puede tomar evaluar todos los valores, también se puede decir para encontrar findFirst/Any .

¿Hay alguna diferencia fundamental que me falta? ¿No entiendo realmente lo que está pasando?


Cuando el javadoc dice "puede que no sea un cortocircuito", simplemente está señalando que no es una operación de cortocircuito y que, dependiendo de los valores, se puede procesar todo el flujo.

findFirst y findAny por otro lado, tienen la garantía de un cortocircuito, ya que nunca tienen que procesar el resto del flujo una vez que estén satisfechos.


Hay una diferencia sutil, porque anyMatch familia de anyMatch usa un predicado, mientras que la familia findAny no lo hace. Técnicamente, findAny() parece a anyMatch(x -> true) y anyMatch(pred) parece a filter(pred).findAny() . Así que aquí tenemos otro problema. Consideremos que tenemos un simple flujo infinito:

Stream<Integer> s = Stream.generate(() -> 1);

Por lo tanto, es cierto que la aplicación de findAny() en dicha transmisión siempre tendrá un cortocircuito y un final, mientras que la aplicación de cualquier anyMatch(pred) depende del predicado. Sin embargo, vamos a filtrar nuestro flujo infinito:

Stream<Integer> s = Stream.generate(() -> 1).filter(x -> x < 0);

¿El flujo resultante es infinito también? Esa es una pregunta difícil. En realidad no contiene elementos, pero para determinar esto (por ejemplo, al usar .iterator().hasNext() ) tenemos que verificar el número infinito de elementos de flujo subyacentes, por lo que esta operación nunca terminará. Yo llamaría a tal flujo infinito también. Sin embargo, el uso de dicha transmisión, anyMatch y findAny nunca terminará:

Stream.generate(() -> 1).filter(x -> x < 0).anyMatch(x -> true); Stream.generate(() -> 1).filter(x -> x < 0).findAny();

Por findAny() tanto, findAny() se garantiza que findAny() termine, depende de las operaciones de flujo intermedio anteriores.

Para concluir, calificaría esa publicación de blog como muy engañosa. En mi opinión, el comportamiento del flujo infinito se explica mejor en JavaDoc oficial.


Según la documentación de Oracle Stream: JavaDoc

Una operación de terminal está en cortocircuito si, cuando se presenta con una entrada infinita, puede terminar en un tiempo finito. Tener una operación de cortocircuito en la tubería es una condición necesaria, pero no suficiente, para que el procesamiento de una corriente infinita termine normalmente en un tiempo finito.

Las cinco funciones tienen la línea:

Esta es una operación de terminal de cortocircuito.

En la descripción de la función.


anyMatch, noneMatch y allMatch devuelven valores booleanos, por lo que es posible que tengan que verificar todo para probar la lógica.

encuentra primero y encuentra a cualquiera. Sólo te importa encontrar lo primero que puedan y devolverlo.

Edición: para un conjunto de datos determinado, se garantiza que los métodos de coincidencia siempre devolverán el mismo valor, sin embargo, los métodos de búsqueda no lo son porque el orden puede variar y afectar a qué valor se devuelve.

El cortocircuito descrito se refiere a los métodos Find que carecen de coherencia para un conjunto de datos determinado.


Respuesta actualizada

Yo diría que la publicación del blog es incorrecta cuando dice "encontrar primero o encontrar, solo necesitamos el primer valor que coincida con el predicado".

En el javadoc para allMatch(Predicate) , anyMatch(Predicate) , noneMatch(Predicate) , findAny() , y findFirst() :

Esta es una operación de terminal de cortocircuito.

Sin embargo, tenga en cuenta que findFirst y findAny no tienen un Predicate . Así que ambos pueden regresar inmediatamente después de ver el primer / cualquier valor. Los otros 3 son condicionales y pueden repetirse para siempre si la condición nunca se dispara.