Ejemplos de interfaces funcionales
En vista de la simplicidad y la versatilidad de las interfaces funcionales, se definieron cierto número de ellas que facilitan algunas operaciones frecuentes en las tareas del programador. Veamos algunas:
Predicate
Predicate se emplea para comprobar una condición en un valor del tipo genérico T. Su método es:
boolean test(T valor);
Devuelve:
truesi la condición se verifica para el valor.falseen caso contrario.
Vamos a comprobar por ejemplo si un Integer es positivo:
Predicate<Integer> esPositivo = x -> x > 0;
Si el método de la interfaz solo tiene un parámetro, se pueden omitir los paréntesis donde se indican los parámetros. Por lo tanto la siguiente sentencia devolverá true:
esPositivo.test(5);
Además, la interfaz tiene otros tres métodos ya implementados por defecto.
Uno de ellos es negate() que devuelve un nuevo predicado con la negación del predicado que lo invoca:
Predicate<Integer> esNegativo = esPositivo.negate();
Otro método por defecto es and() que devuelve un predicado que es una conjunción del predicado invocante y del que se pasa por parámetro.
El método test devolverá true cuando los dos predicados sean ciertos para el valor que se le pase como parámetro. Los tipos genéricos de los dos predicados tienen que ser del mismo tipo. Ejemplo:
Predicate<Integer> esPar = n -> n %2 == 0;
Predicate<Integer> esPositivoYPar = esPar.and(esPositivo);
El otro método por defecto es or() que devuelve true si alguno de los predicados es cierto.
Function
Function a partir del argumento de tipo T, devuelve el resultado de tipo R. Su método abstracto es:
R apply(T x);
Por ejemplo, si queremos definir una función que calcula el cuadrado de un valor real:
Function<Double, Double> cuadrado = x -> x*x;
cuadrado.apply(2.0); // Esto es el valor 4.0
Además, cuenta con 3 métodos por defecto.
Consumer
Consumer sirve para realizar una tarea a partir de un argumento de entrada. Su método abstracto es:
void accept(T t);
Recibe un valor de la clase T y realiza operaciones sin devolver nada.
Por ejemplo, si queremos mostrar por pantalla saludos a distintos clientes:
Consumer<Cliente> saludoCliente = c -> System.out.println("Hola " + c.getNombre());
Cliente cliente = new Cliente("123","Manuel");
saludoCliente.accept(cliente); //Mostrará por pantalla "Hola Manuel"
BinaryOperator
La interfaz funcional BinaryOperator<T> se usa cuando queremos aplicar una operación binaria (sumar, restar, multiplicar, etc.) sobre dos valores del mismo tipo y obtener un resultado del mismo tipo.
Su método abstracto es:
T apply(T t, T u);
Ejemplo:
import java.util.function.BinaryOperator;
BinaryOperator<Integer> suma = (a, b) -> a + b; // Para sumar dos números
System.out.println(suma.apply(5, 3)); // 8