ejemplo java lambda java-8 java-9 peek

ejemplo - Método Stream.peek() en Java 8 vs Java 9



stream java 8 ejemplo (2)

Estoy en el progreso de aprender a través de las expresiones lambda de Java 8 y me gustaría preguntar sobre el siguiente fragmento de código Java relacionado con el método peek en la interfaz de funciones que he encontrado.

Al ejecutar el programa en IDE, no da salida. Esperaba que daría 2, 4, 6 .

import java.util.Arrays; import java.util.List; public class Test_Q3 { public Test_Q3() { } public static void main(String[] args) { List<Integer> values = Arrays.asList(1, 2, 3); values.stream() .map(n -> n * 2) .peek(System.out::print) .count(); } }


¿Supongo que está ejecutando esto en Java 9? No está alterando la propiedad SIZED de la transmisión, por lo que no es necesario ejecutar ni un map ni un peek .

En otras palabras, todo lo que le importa es count como el resultado final, pero mientras tanto no altera el tamaño inicial de la List de ninguna manera (a través de un filter por ejemplo o distinct ). Esta es una optimización realizada en Streams.

Por cierto, incluso si agrega un filtro ficticio, esto mostrará lo que espera:

values.stream () .map(n -> n*2) .peek(System.out::print) .filter(x -> true) .count();


Aquí hay algunas citas relevantes de la interfaz Javadoc de Stream :

Se permite una implementación de flujo latitud significativa en la optimización del cálculo del resultado. Por ejemplo, una implementación de flujo es libre de eludir operaciones (o etapas completas) de una tubería de flujo, y por lo tanto, elude la invocación de parámetros de comportamiento, si puede probar que no afectaría el resultado del cálculo . Esto significa que los efectos secundarios de los parámetros de comportamiento no siempre se pueden ejecutar y no se debe confiar en ellos, a menos que se especifique lo contrario (como las operaciones de terminal para cada uno y cada pedido). (Para ver un ejemplo específico de dicha optimización, consulte la nota de API documentada en la operación count (). Para obtener más detalles, consulte la sección de efectos secundarios de la documentación del paquete de transmisión).

Y más específicamente del método Javadoc of count() :

Nota de API:

Una implementación puede optar por no ejecutar el flujo de flujo (secuencialmente o en paralelo) si es capaz de calcular el recuento directamente desde la fuente del flujo . En tales casos, no se atravesarán elementos fuente y no se evaluarán operaciones intermedias . Los parámetros de comportamiento con efectos secundarios, que se desaconsejan fuertemente, excepto en casos inofensivos como la depuración, pueden verse afectados. Por ejemplo, considere la siguiente secuencia:

List<String> l = Arrays.asList("A", "B", "C", "D"); long count = l.stream().peek(System.out::println).count();

El número de elementos cubiertos por la fuente del flujo, una Lista, es conocido y la operación intermedia, peek, no inyecta ni elimina elementos del flujo (como puede ser el caso de flatMap o operaciones de filtro). Por lo tanto, el recuento es el tamaño de la Lista y no hay necesidad de ejecutar la canalización y, como efecto secundario, imprimir los elementos de la lista.

Estas citas solo aparecen en el Javadoc de Java 9, por lo que debe ser una nueva optimización.