son que las interfaces funciones funcionales expresiones explicacion ejercicios anonimas java lambda java-8

que - java 8 lambda explicacion



¿Las expresiones lambda tienen otro uso que no sea guardar líneas de código? (9)

Iteración interna

Al iterar colecciones de Java, la mayoría de los desarrolladores tienden a obtener un elemento y luego procesarlo . Esto es, saque ese elemento y luego úselo, o vuelva a insertarlo, etc. Con las versiones anteriores a 8 de Java, puede implementar una clase interna y hacer algo como:

numbers.forEach(new Consumer<Integer>() { public void accept(Integer value) { System.out.println(value); } });

Ahora con Java 8 puede hacerlo mejor y menos detallado con:

numbers.forEach((Integer value) -> System.out.println(value));

o mejor

numbers.forEach(System.out::println);

Comportamientos como argumentos

Adivina el siguiente caso:

public int sumAllEven(List<Integer> numbers) { int total = 0; for (int number : numbers) { if (number % 2 == 0) { total += number; } } return total; }

Con la interfaz de Java 8 Predicate puede hacerlo mejor así:

public int sumAll(List<Integer> numbers, Predicate<Integer> p) { int total = 0; for (int number : numbers) { if (p.test(number)) { total += number; } } return total; }

Llamándolo así:

sumAll(numbers, n -> n % 2 == 0);

Fuente: DZone - Por qué necesitamos expresiones Lambda en Java

¿Las expresiones lambda tienen otro uso que no sea guardar líneas de código?

¿Hay características especiales proporcionadas por lambdas que resolvieron problemas que no fueron fáciles de resolver? El uso típico que he visto es que en lugar de escribir esto:

Comparator<Developer> byName = new Comparator<Developer>() { @Override public int compare(Developer o1, Developer o2) { return o1.getName().compareTo(o2.getName()); } };

Podemos usar una expresión lambda para acortar el código:

Comparator<Developer> byName = (Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName());


Guardar líneas de código puede verse como una nueva característica, si le permite escribir una parte sustancial de la lógica de una manera más corta y clara, lo que lleva menos tiempo para que otros lo lean y comprendan.

Sin expresiones lambda (y / o referencias de métodos) Stream canalizaciones de Stream habrían sido mucho menos legibles.

Piense, por ejemplo, cómo se vería la siguiente tubería Stream si reemplazara cada expresión lambda con una instancia de clase anónima.

List<String> names = people.stream() .filter(p -> p.getAge() > 21) .map(p -> p.getName()) .sorted((n1,n2) -> n1.compareToIgnoreCase(n2)) .collect(Collectors.toList());

Podría ser:

List<String> names = people.stream() .filter(new Predicate<Person>() { @Override public boolean test(Person p) { return p.getAge() > 21; } }) .map(new Function<Person,String>() { @Override public String apply(Person p) { return p.getName(); } }) .sorted(new Comparator<String>() { @Override public int compare(String n1, String n2) { return n1.compareToIgnoreCase(n2); } }) .collect(Collectors.toList());

Esto es mucho más difícil de escribir que la versión con expresiones lambda, y es mucho más propenso a errores. También es más difícil de entender.

Y esta es una tubería relativamente corta.

Para hacer que esto sea legible sin expresiones lambda y referencias de métodos, habría tenido que definir variables que contengan las diversas instancias de interfaz funcional que se utilizan aquí, lo que habría dividido la lógica de la tubería, lo que dificulta su comprensión.


Hay muchos beneficios de usar lambdas en lugar de las siguientes clases internas:

  • Haga que el código sea más compacto y expresivo sin introducir más semántica de sintaxis de lenguaje. usted ya dio un ejemplo en su pregunta.

  • Al usar lambdas, está contento de programar con operaciones de estilo funcional en flujos de elementos, como transformaciones de reducción de mapas en colecciones. consulte la documentación de los paquetes java.util.function y java.util.stream .

  • No hay un archivo de clases físicas generado para lambdas por el compilador. Por lo tanto, hace que sus aplicaciones entregadas sean más pequeñas. ¿Cómo se asigna la memoria a lambda?

  • El compilador optimizará la creación de lambda si la lambda no accede a variables fuera de su alcance, lo que significa que la instancia de lambda solo se crea una vez por la JVM. para obtener más detalles, puede ver la respuesta de @ Holger a la pregunta ¿El almacenamiento en caché de referencia de método es una buena idea en Java 8? .

  • Lambdas puede implementar interfaces de marcadores múltiples además de la interfaz funcional, pero las clases internas anónimas no pueden implementar más interfaces, por ejemplo:

    // v--- create the lambda locally. Consumer<Integer> action = (Consumer<Integer> & Serializable) it -> {/*TODO*/};


Las expresiones Lambda no cambian el conjunto de problemas que puede resolver con Java en general, pero definitivamente facilitan la resolución de ciertos problemas, solo por la misma razón por la que ya no estamos programando en lenguaje ensamblador. Eliminar las tareas redundantes del trabajo del programador hace la vida más fácil y permite hacer cosas que de otro modo no tocarías, solo por la cantidad de código que tendrías que producir (manualmente).

Pero las expresiones lambda no solo guardan líneas de código. Las expresiones Lambda le permiten definir funciones , algo para lo que podría usar clases internas anónimas como solución alternativa antes, por eso puede reemplazar las clases internas anónimas en estos casos, pero no en general.

En particular, las expresiones lambda se definen de forma independiente a la interfaz funcional a la que se convertirán, por lo que no hay miembros heredados a los que puedan acceder, además, no pueden acceder a la instancia del tipo que implementa la interfaz funcional. Dentro de una expresión lambda, this y super tienen el mismo significado que en el contexto circundante, vea también esta respuesta . Además, no puede crear nuevas variables locales que sombreen las variables locales del contexto circundante. Para la tarea prevista de definir una función, esto elimina muchas fuentes de error, pero también implica que para otros casos de uso, puede haber clases internas anónimas que no se pueden convertir a una expresión lambda, incluso si se implementa una interfaz funcional.

Además, la construcción new Type() { … } garantiza producir una nueva instancia distinta (como siempre lo hace new ). Las instancias anónimas de clase interna siempre mantienen una referencia a su instancia externa si se crean en un contexto no static . Por el contrario, las expresiones lambda solo capturan una referencia a this cuando es necesario, es decir, si acceden a this o a un miembro no static . Y producen instancias de una identidad intencionalmente no especificada, lo que permite que la implementación decida en tiempo de ejecución si reutilizar las instancias existentes (consulte también " ¿Una expresión lambda crea un objeto en el montón cada vez que se ejecuta? ").

Estas diferencias se aplican a su ejemplo. Su construcción de clase interna anónima siempre producirá una nueva instancia, también puede capturar una referencia a la instancia externa, mientras que su (Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName()) es un expresión lambda sin captura que se evaluará en un singleton en implementaciones típicas. Además, no produce un archivo .class en su disco duro.

Dadas las diferencias entre ambos, semántico y rendimiento, las expresiones lambda pueden cambiar la forma en que los programadores resolverán ciertos problemas en el futuro, por supuesto, también debido a las nuevas API que abarcan ideas de programación funcional utilizando las nuevas características del lenguaje. Consulte también la expresión lambda de Java 8 y los valores de primera clase .


Las lambdas son simplemente azúcar sintáctica para clases anónimas.

Antes de lambdas, las clases anónimas se pueden usar para lograr lo mismo. Cada expresión lambda se puede convertir a una clase anónima.

Si está utilizando IntelliJ IDEA, puede realizar la conversión por usted:

  • Pon el cursor en la lambda
  • Presione alt / opción + enter


Los lenguajes de programación no son para que las máquinas los ejecuten.

Son para que los programadores piensen .

Los idiomas son una conversación con un compilador para convertir nuestros pensamientos en algo que una máquina puede ejecutar. Una de las principales quejas sobre Java de las personas que lo utilizan desde otros idiomas (o lo dejan para otros idiomas) solía ser que obliga a un cierto modelo mental en el programador (es decir, todo es una clase).

No voy a considerar si eso es bueno o malo: todo es una compensación. Pero las lambdas de Java 8 permiten a los programadores pensar en términos de funciones , que es algo que anteriormente no se podía hacer en Java.

Es lo mismo que un programador de procedimientos que aprende a pensar en términos de clases cuando se trata de Java: los ve pasar gradualmente de clases que son estructuras glorificadas y tienen clases ''auxiliares'' con un montón de métodos estáticos y pasan a algo que se parece más a un diseño OO racional (mea culpa).

Si solo piensa en ellos como una forma más corta de expresar clases internas anónimas, entonces probablemente no los encontrará muy impresionantes de la misma manera que el programador de procedimientos anterior probablemente no pensó que las clases fueran una gran mejora.


Para responder a su pregunta, el hecho es que lambdas no le permite hacer nada que no pudiera hacer antes de java-8, sino que le permite escribir código más conciso . Los beneficios de esto es que su código será más claro y flexible.


Sí, hay muchas ventajas.

  • No es necesario definir toda la clase, podemos pasar la implementación de la función como referencia.
    • Internamente, la creación de la clase creará un archivo .class, mientras que si usa lambda, el compilador evita la creación de la clase porque en lambda está pasando la implementación de la función en lugar de la clase.
  • La reutilización del código es mayor que antes
  • Y como dijiste, el código es más corto que la implementación normal.

Una cosa que aún no veo mencionada es que una lambda le permite definir la funcionalidad donde se usa .

Entonces, si tiene alguna función de selección simple, no necesita colocarla en un lugar separado con un montón de repeticiones, simplemente escriba una lambda que sea concisa y relevante a nivel local.