Introducción Expresiones Lambda
Introducción expresiones lambda
Las expresiones lambda fueron introducidas en Java 8 y proporcionan una forma más compacta y funcional de escribir código, especialmente cuando se trata de implementar interfaces funcionales (interfaces que tienen solo un método abstracto). Las expresiones lambda permiten pasar funciones como argumentos a métodos, lo que facilita el trabajo con funciones de orden superior y proporciona un estilo de programación más declarativo y conciso.
| Concepto | Descripción |
|---|---|
| Definición | Función anónima que implementa interfaces funcionales (un solo método abstracto). |
| Sintaxis | (parameters) -> expression |
| Ventajas | - Código más conciso- Facilita la programación funcional- Mejora la legibilidad |
| Interfaces Funcionales | - Function<T, R>: Entrada T, salida R |
Predicate<T>: EntradaT, devuelvebooleanConsumer<T>: EntradaT, sin retornoSupplier<T>: No toma entrada, devuelveT| | Ejemplos | -Function:(a) -> a + 1Predicate:(n) -> n % 2 == 0Consumer:(s) -> System.out.println(s)Supplier:() -> Math.random()| | Uso en Colecciones | -forEach:list.forEach(item -> System.out.println(item));Stream:list.stream().filter(s -> s.startsWith("J")).collect(Collectors.toList());|
¿Qué es una expresión Lambda?
Una expresión lambda es una función anónima que se puede usar para implementar métodos de interfaces funcionales de manera más compacta. Se define mediante una sintaxis más simple que permite crear instancias de interfaces funcionales sin necesidad de crear clases o métodos adicionales.
Sintaxis básica de una expresión lambda:
(parameters) -> expression
parameters: Son los parámetros de entrada de la función, que pueden ser uno o más.->: Es el operador que separa los parámetros de la expresión lambda.expression: Es la implementación del método de la interfaz funcional.
Ejemplo de una expresión Lambda:
Supongamos que tenemos una interfaz funcional que define un método para sumar dos números:
@FunctionalInterface
interface Sum {
int add(int a, int b);
}
Una expresión lambda que implementa esta interfaz sería:
Sum sum = (a, b) -> a + b;
System.out.println(sum.add(5, 3)); // Imprime: 8
En este caso, la expresión lambda (a, b) -> a + b implementa el método add() de la interfaz Sum.
Ventajas de las Expresiones Lambda
-
Concisión y claridad: Las expresiones lambda hacen que el código sea más compacto y fácil de leer, eliminando la necesidad de crear clases anónimas o métodos adicionales para interfaces funcionales.
Ejemplo con clase anónima:
Comparator<String> comparator = new Comparator<String>() { public int compare(String s1, String s2) { return s1.compareTo(s2); } };Ejemplo con lambda:
Comparator<String> comparator = (s1, s2) -> s1.compareTo(s2); -
Fomenta la programación funcional: Permite trabajar con funciones de manera más fluida, lo que facilita el uso de conceptos de programación funcional como las funciones de orden superior y el paso de funciones como argumentos.
-
Mejora la legibilidad del código: Al reducir la cantidad de código necesario para realizar tareas como la creación de implementaciones de interfaces, las expresiones lambda permiten que el propósito de una función sea más claro.
Tipos de Interfaces Funcionales
Las expresiones lambda funcionan con interfaces funcionales. Estas son interfaces que tienen exactamente un método abstracto. En Java, estas interfaces están definidas en el paquete java.util.function.
Ejemplos de interfaces funcionales comunes:
-
Function<T, R>: Representa una función que toma un argumento de tipoTy devuelve un valor de tipoR.Function<Integer, String> intToString = i -> "Número: " + i; System.out.println(intToString.apply(5)); // Imprime: "Número: 5" -
Predicate<T>: Representa una función que toma un argumento de tipoTy devuelve un valor booleano.Predicate<Integer> isEven = n -> n % 2 == 0; System.out.println(isEven.test(4)); // Imprime: true -
Consumer<T>: Representa una función que toma un argumento de tipoTy no devuelve ningún valor (acción de consumo).Consumer<String> print = s -> System.out.println(s); print.accept("Hola Lambda!"); // Imprime: "Hola Lambda!" -
Supplier<T>: Representa una función que no toma ningún argumento y devuelve un valor de tipoT.Supplier<Double> randomValue = () -> Math.random(); System.out.println(randomValue.get()); // Imprime un número aleatorio
Uso de Expresiones Lambda con Colecciones
Las expresiones lambda son especialmente útiles cuando se trabaja con colecciones en Java, especialmente en operaciones como filtrado, mapeo y reducción. Java 8 introduce el uso de Streams para trabajar con colecciones de una manera funcional y declarativa.
Ejemplo con forEach() y Stream:
List<String> list = Arrays.asList("Java", "Python", "JavaScript");
list.forEach(item -> System.out.println(item)); // Imprime cada elemento de la lista
Ejemplo con filter() y map() en Streams:
List<String> list = Arrays.asList("Java", "Python", "JavaScript", "Ruby");
List<String> filteredList = list.stream()
.filter(s -> s.startsWith("J")) // Filtra los elementos que empiezan con 'J'
.map(String::toUpperCase) // Convierte los elementos a mayúsculas
.collect(Collectors.toList());
System.out.println(filteredList); // Imprime: [JAVA, JAVASCRIPT]
Sintaxis de Expresiones Lambda Complejas
Las expresiones lambda también pueden tener múltiples instrucciones, pero deben estar encerradas en un bloque de código.
Function<Integer, String> checkNumber = (n) -> {
if (n % 2 == 0) {
return "Par";
} else {
return "Impar";
}
};
System.out.println(checkNumber.apply(5)); // Imprime: "Impar"