Lambdas y referencias a métodos (::)
La base de la programación funcional en Java 8
De clases anónimas a lambdas
Antes de Java 8, pasar comportamiento como argumento requería clases anónimas: mucho boilerplate para expresar algo simple. Las lambdas eliminan ese ruido.
// Antes de Java 8: clase anónima
List<String> nombres = Arrays.asList("Carlos", "Ana", "Luis");
Collections.sort(nombres, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
}); // Con lambda: misma operación, sin el boilerplate
Collections.sort(nombres, (a, b) -> a.compareTo(b));
// Aún más corto con referencia a método
Collections.sort(nombres, String::compareTo); Sintaxis de las lambdas
Una lambda es una función anónima: (parámetros) -> cuerpo. El tipo de los parámetros se
infiere del contexto — el compilador sabe qué interfaz funcional se espera y deduce los tipos.
// Formas de lambda según el número de parámetros y el cuerpo
// Sin parámetros
Runnable r = () -> System.out.println("ejecutando");
// Un parámetro (los paréntesis son opcionales)
Consumer<String> imprimir = s -> System.out.println(s);
// Varios parámetros
Comparator<Integer> comp = (a, b) -> a - b;
// Cuerpo con varias sentencias: necesita llaves y return explícito
Function<String, String> procesar = texto -> {
String limpio = texto.trim();
return limpio.toLowerCase();
};
Referencias a métodos (::)
Una referencia a método es una lambda que no hace nada más que llamar a un método ya existente. Es más legible cuando el cuerpo de la lambda sería simplemente una llamada directa.
// Cuatro tipos de referencia a método
// 1. Método estático: Clase::metodoEstatico
Function<String, Integer> parse = Integer::parseInt;
// 2. Método de instancia sobre un objeto concreto: objeto::metodo
String prefijo = "Hola, ";
Function<String, String> saludar = prefijo::concat;
// 3. Método de instancia sobre el parámetro: Clase::metodoInstancia
Function<String, String> mayus = String::toUpperCase;
Predicate<String> vacio = String::isEmpty;
// 4. Constructor: Clase::new
Supplier<ArrayList<String>> fabrica = ArrayList::new; Ejemplo integrado
// Ejemplo integrado: filtrar, transformar e imprimir una lista
List<String> nombres = Arrays.asList("Ana", "luis", "EVA", "carlos");
nombres.stream()
.map(String::toLowerCase) // referencia a método de instancia
.filter(n -> n.startsWith("a")) // lambda predicado
.forEach(System.out::println); // referencia a método estático de instancia
// Salida: ana