tutorial suma fundamento funcional expresiones calculo java lambda

fundamento - suma lambda java



¿Dónde se evalúan las expresiones lambda de Java 8? (4)

¿Se evalúan las expresiones lambda en el lugar donde las escribimos o en cualquier otra clase de Java?

Por ejemplo :

Stream<Student> absent = students.values().stream().filter(s -> !s.present());

¿Se ejecutará inmediatamente la expresión lambda anterior que se pasa al método de filtro en una clase dada donde el código se escribe O en otra clase y tomará más tiempo (en términos de nano segundos) que si el código se escribiera en un estilo de codificación convencional? antes de Java 8?


Cuando compile sus fuentes, el compilador insertará una instrucción de código de byte invokedynamic para la expresión lambda que utiliza. La implementación real (que en su caso es un Predicate ) se creará en tiempo de ejecución a través de ASM . Ni siquiera estará presente en el disco duro cuando lo ejecute, lo que significa que la clase se genera en la memoria, no habrá un archivo .class para Predicate . Esa es una gran diferencia entre una clase anónima, por ejemplo, que generará un archivo de class cuando lo compile .

Puede ver el archivo generado para el Predicate si ejecuta su ejemplo con:

-Djdk.internal.lambda.dumpProxyClasses=/Your/Path/Here

De lo contrario, la respuesta de Eran es correcta, las Stream son controladas por la operación del terminal, si no está presente, no se ejecuta nada. Debes leer absolutamente la excelente respuesta de Holger sobre diferencias aún más interesantes.


El cuerpo de la expresión lambda pasada al método de filtro en su ejemplo no se ejecutará en absoluto, ya que el filter es una operación intermedia, que solo se ejecuta para las Stream que terminan en una operación de terminal, como collect , para forEach , etc. ...

Si agrega una operación de terminal, como la recopilación de los elementos de la Stream a una List :

List<Student> absent = students.values().stream().filter(s -> !s.present()).collect(Collectors.toList());

el cuerpo de la expresión lambda se ejecutará para cada elemento de su Stream , para que la operación del terminal pueda producir su salida.

Tenga en cuenta que este comportamiento no cambiaría si pasara una instancia de clase anónima o alguna otra implementación de la interfaz Predicate a su método de filter lugar de la expresión lambda.


Las expresiones Lambda son esencialmente objetos con un solo método, por lo que se evalúan cada vez que se llama a ese método.

En tu caso particular nunca son evaluados. A Stream no evalúa las expresiones hasta que llama a una operación de terminación ( collect , findAny , etc.)


Las expresiones se evalúan de forma perezosa, lo que significa que solo se evaluarán realmente cuando intentes "terminar" la secuencia, es decir, usar una operación que toma una secuencia pero devuelve otra cosa, como collect , min , max , reduce , etc. Las operaciones que toman un flujo como entrada y devuelven un flujo como salida suelen ser perezosas.