Interfaces funcionales de Java 8

Java 8 新特性Nuevas características de Java 8


Una interfaz funcional (Functional Interface) es una interfaz que tiene exactamente un método abstracto, pero puede tener varios métodos no abstractos.

Las interfaces funcionales pueden convertirse implícitamente en expresiones lambda.

En las expresiones lambda y las referencias a métodos (que en realidad también pueden considerarse expresiones lambda).

Por ejemplo, si se define una interfaz funcional como la siguiente:

@FunctionalInterface
interface GreetingService 
{
    void sayMessage(String message);
}

Entonces se puede utilizar una expresión lambda para representar una implementación de esa interfaz (nota: antes de Java 8 generalmente se implementaba con una clase anónima):

GreetingService greetService1 = message -> System.out.println("Hello " + message);

Las interfaces funcionales pueden admitir lambdas de manera amigable con las funciones existentes.

Interfaces funcionales ya existentes antes de JDK 1.8:

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.security.PrivilegedAction
  • java.util.Comparator
  • java.io.FileFilter
  • java.nio.file.PathMatcher
  • java.lang.reflect.InvocationHandler
  • java.beans.PropertyChangeListener
  • java.awt.event.ActionListener
  • javax.swing.event.ChangeListener

Interfaces funcionales añadidas en JDK 1.8:

  • java.util.function

java.util.function contiene muchas clases para apoyar la programación funcional de Java. Las interfaces funcionales en este paquete son:

N.º Interfaz y descripción
1 BiConsumer<T,U>

Representa una operación que acepta dos parámetros de entrada y no devuelve ningún resultado.

2 BiFunction<T,U,R>

Representa un método que acepta dos parámetros de entrada y devuelve un resultado.

3 BinaryOperator<T>

Representa una operación sobre dos operandos del mismo tipo y devuelve un resultado del mismo tipo que los operandos.

4 BiPredicate<T,U>

Representa un método de valor booleano con dos parámetros.

5 BooleanSupplier

Representa un proveedor de resultados de tipo booleano.

6 Consumer<T>

Representa una operación que acepta un parámetro de entrada y no devuelve nada.

7 DoubleBinaryOperator

Representa una operación sobre dos operandos de tipo double y devuelve un resultado de tipo double.

8 DoubleConsumer

Representa una operación que acepta un parámetro de tipo double y no devuelve ningún resultado.

9 DoubleFunction<R>

Representa un método que acepta un parámetro de tipo double y devuelve un resultado.

10 DoublePredicate

Representa un método de valor booleano que tiene un parámetro de tipo double.

11 DoubleSupplier

Representa un proveedor de valores de tipo double.

12 DoubleToIntFunction

Acepta una entrada de tipo double y devuelve un resultado de tipo int.

13 DoubleToLongFunction

Acepta una entrada de tipo double y devuelve un resultado de tipo long.

14 DoubleUnaryOperator

Acepta un parámetro de tipo double y el tipo de retorno también es double.

15 Function<T,R>

Acepta un parámetro de entrada y devuelve un resultado.

16 IntBinaryOperator

Acepta dos parámetros de tipo int y el tipo de retorno también es int.

17 IntConsumer

Acepta un parámetro de entrada de tipo int, sin valor de retorno.

18 IntFunction<R>

Acepta un parámetro de entrada de tipo int y devuelve un resultado.

19 IntPredicate

Acepta un parámetro de entrada de tipo int y devuelve un resultado booleano.

20 IntSupplier

Sin parámetros, devuelve un resultado de tipo int.

21 IntToDoubleFunction

Acepta una entrada de tipo int y devuelve un resultado de tipo double.

22 IntToLongFunction

Acepta una entrada de tipo int y devuelve un resultado de tipo long.

23 IntUnaryOperator

Acepta un parámetro de tipo int y el tipo de retorno también es int.

24 LongBinaryOperator

Acepta dos parámetros de tipo long y el tipo de retorno también es long.

25 LongConsumer

Acepta un parámetro de entrada de tipo long, sin valor de retorno.

26 LongFunction<R>

Acepta un parámetro de entrada de tipo long y devuelve un resultado.

27 LongPredicate

Acepta un parámetro de entrada de tipo long y devuelve un resultado de tipo booleano.

28 LongSupplier

Sin parámetros, devuelve un valor de tipo long.

29 LongToDoubleFunction

Acepta una entrada de tipo long y devuelve un resultado de tipo double.

30 LongToIntFunction

Acepta una entrada de tipo long y devuelve un resultado de tipo int.

31 LongUnaryOperator

Acepta un parámetro de tipo long y el tipo de retorno también es long.

32 ObjDoubleConsumer<T>

Acepta un parámetro de entrada de tipo Object y otro de tipo double, sin valor de retorno.

33 ObjIntConsumer<T>

Acepta un parámetro de entrada de tipo Object y otro de tipo int, sin valor de retorno.

34 ObjLongConsumer<T>

Acepta un parámetro de entrada de tipo Object y otro de tipo long, sin valor de retorno.

35 Predicate<T>

Acepta un parámetro de entrada y devuelve un resultado booleano.

36 Supplier<T>

Sin parámetros, devuelve un resultado.

37 ToDoubleBiFunction<T,U>

Acepta dos parámetros de entrada y devuelve un resultado de tipo double.

38 ToDoubleFunction<T>

Acepta un parámetro de entrada y devuelve un resultado de tipo double.

39 ToIntBiFunction<T,U>

Acepta dos parámetros de entrada y devuelve un resultado de tipo int.

40 ToIntFunction<T>

Acepta un parámetro de entrada y devuelve un resultado de tipo int.

41 ToLongBiFunction<T,U>

Acepta dos parámetros de entrada y devuelve un resultado de tipo long.

42 ToLongFunction<T>

Acepta un parámetro de entrada y devuelve un resultado de tipo long.

43 UnaryOperator<T>

Acepta un parámetro de tipo T y el tipo de retorno también es T.


Ejemplo de interfaz funcional

La interfaz Predicate<T> es una interfaz funcional que acepta un parámetro de entrada T y devuelve un resultado booleano.

Esta interfaz contiene varios métodos predeterminados para combinar Predicate en otra lógica compleja (por ejemplo: AND, OR, NOT).

Esta interfaz se utiliza para comprobar si un objeto es true o false.

Podemos entender el uso de la interfaz funcional Predicate<T> mediante el siguiente ejemplo (Java8Tester.java):

Archivo Java8Tester.java

import java.util.Arrays; import java.util.List; import java.util.function.Predicate; public class Java8Tester { public static void main(String args[]){ List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); // Predicate<Integer> predicate = n -> true //n es un parámetro que se pasa al método test de la interfaz Predicate. //Si n existe, el método test devuelve true. System.out.println("Imprimir todos los datos:"); //Pasar el parámetro n eval(list, n->true); // Predicate<Integer> predicate1 = n -> n%2 == 0 //n es un parámetro que se pasa al método test de la interfaz Predicate. //Si n%2 es 0, el método test devuelve true. System.out.println("Imprimir todos los números pares:"); eval(list, n-> n%2 == 0 ); // Predicate<Integer> predicate2 = n -> n > 3 //n es un parámetro que se pasa al método test de la interfaz Predicate. //Si n es mayor que 3, el método test devuelve true. System.out.println("Imprimir todos los números mayores que 3:"); eval(list, n-> n > 3 ); } public static void eval(List<Integer> list, Predicate<Integer> predicate) { for(Integer n: list) { if(predicate.test(n)) { System.out.println(n + " "); } } } }

Al ejecutar el script anterior, el resultado es:

$ javac Java8Tester.java 
$ java Java8Tester
输出所有数据:
1 
2 
3 
4 
5 
6 
7 
8 
9 
输出所有偶数:
2 
4 
6 
8 
输出大于 3 的所有数字:
4 
5 
6 
7 
8 
9 

Java 8 新特性Nuevas características de Java 8

Otras extensiones