En la anterior entrega vimos lo que son las expresiones lambda. En esta ocasión veremos las Functional Interfaces.
Una Functional Interface es una interfaz Java que contiene un solo método abstracto. Esto garantiza que se pueda usar con expresiones lambda.
¿Cómo definimos una Functional Interface (interface funcional)? Con la anotación @FunctionalInterface un ejemplo sería este bloque:
@FunctionalInterface interface MyInterfaceFuncional { void hacerAlgo(); }
Como vimos anteriormente existen cuatro principales:
- Consumer: Puede o no recibir algún valor y no devolver nada.
- Function: Puede tomar dos valores de distinto tipo y devolver un valor en específico.
- Predicate: Puede tomar valores y devolver un valor booleano true o false.
- Supplier: No recibe valores, pero devuelve un valor.
Consumer.
@FunctionalInterface interface Consumer<T> { void accept(T t); }
Function.
@FunctionalInterface interface Function<T, R> { R apply(T t); }
Predicate.
@FunctionalInterface interface Predicate<T> { boolean test(T t); }
Supplier.
@FunctionalInterface interface Supplier<T> { T get(); }
Para usarlas, es necesario importarlas:
import java.util.function.Consumer;//interface import java.util.function.Function;//interface import java.util.function.Supplier;//interface import java.util.function.Predicate;//interface
Ejemplo 1. Crear una Interface funcional que sume 3 números tipo Integer.
@FunctionalInterface interface Suma { Integer sumar(Integer x, Integer y , Integer z); }
Su implementación sería la siguiente:
Suma operacion = (a, b, c) -> a + b + c;
Integer a, b, c; a = 23; b = 3; c = 4; Integer resultado = operacion .sumar(a,b,c);
Interfaces funcionales y referencias a métodos
Las referencias a métodos proporcionan una notación abreviada para las expresiones lambda que invocan un solo método. Ofrecen una forma alternativa de representar las expresiones lambda de forma más concisa y expresiva. Son especialmente útiles cuando el único propósito de la expresión lambda es invocar un método existente.
Los 4 tipos de referencia a métodos:
- Referencia a un método estático: `ClassName::staticMethodName`.
- Referencia a un método de instancia de un objeto específico: `instance::instanceMethodName`.
- Referencia a un método de instancia de un objeto arbitrario de un tipo específico: `ClassName::instanceMethodName`.
- Referencia a un constructor: `ClassName::new`.
Ejemplo 2. De esta clase hacer uso de una referencia a método estático.
package com.inforhomex; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; public class TestLambdas{ public static void main(String[] args){ List<String> nombres = new ArrayList<String>(); nombres.add("Tomas"); nombres.add("Azucena"); nombres.add("Leopoldo"); nombres.add("Miguel"); nombres.add("Berenice"); nombres.add("Ricardo"); System.out.println("\n--- Usando Consumer ---"); Consumer<String> consumir = (n) -> { System.out.printf("Hola, %s\n",n); }; nombres.forEach(consumir); } }
Resultado:
package com.inforhomex; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; public class TestLambdas { // Método estático que será referenciado public static void saludar(String nombre) { System.out.printf("Hola, %s\n", nombre); } public static void main(String[] args) { List<String> nombres = new ArrayList<String>(); nombres.add("Tomas"); nombres.add("Azucena"); nombres.add("Leopoldo"); nombres.add("Miguel"); nombres.add("Berenice"); nombres.add("Ricardo"); System.out.println("\n--- Usando Consumer con referencia a método estático ---"); // Referencia al método estático Consumer<String> consumir = TestLambdas::saludar; // Aplicar el Consumer a cada elemento nombres.forEach(consumir); } }
Ventajas de Expresiones Lambda en Java:
- Código más conciso y legible: Evitan clases anónimas largas.
- Menos boilerplate: Se escribe solo la lógica, no toda la estructura.
- Mayor expresividad: El código refleja directamente la intención (ej. `list.forEach(x -> ...)`).
- Facilitan programación funcional: Se integran con Streams y APIs modernas.
- Mejor mantenimiento: Más fácil de leer y modificar.
Ventajas de Functional Interfaces:
- Definen contratos claros: Una sola operación abstracta (ej. `Consumer`, `Predicate`, `Function`).
- Compatibles con lambdas y referencias de método: Se usan como destino natural de expresiones lambda.
- Reutilización: Interfaces estándar en `java.util.function` evitan reinventar la rueda.
- Flexibilidad: Permiten pasar comportamiento como parámetro (ej. estrategia, filtros, transformaciones).
- Integración con APIs modernas: Streams, Optional, CompletableFuture, etc.
En conclusión: Las expresiones lambdas simplifican la escritura de lógica y las functional interfaces permiten tratar el comportamiento como datos, lo que hace el código más limpio, flexible y poderoso.
Enlaces:
https://medium.com/@nagarjun_nagesh/functional-interfaces-in-java-fe5ebf5bafedhttps://alquimistadecodigo.blogspot.com/2024/11/expresiones-lambda.html

Comentarios
Publicar un comentario