您的位置:

Java函数式接口

导言

Java 8 自带函数式编程的支持,提供了函数式接口、Lambda 表达式、方法引用、流和并行等新特性。本文将围绕函数式接口展开讲述。

函数式接口

函数式接口指只包含一个抽象方法的接口。通过注解 @FunctionalInterface 可以告诉编译器对该接口进行检查,确保其符合函数式接口的定义。函数式接口可以使用 Lambda 表达式和方法引用两种方式来创建对象。

创建函数式接口

@FunctionalInterface
public interface MyFunctionalInterface {
    void doSomething();
}

使用Lambda表达式

MyFunctionalInterface myLambda = () -> {
        System.out.println("I'm a Lambda expression");
    };
myLambda.doSomething();

上述代码用 Lambda 表达式实现了 MyFunctionalInterface 接口中唯一的抽象方法 doSomething()。

使用方法引用

MyObject myObj = new MyObject();
MyFunctionalInterface myMethodRef = myObj::myMethod;
myMethodRef.doSomething();

上述代码使用方法引用创建了一个 MyFunctionalInterface 的实例。myObj::myMethod 表示使用 myObj 类的 myMethod 方法来实现 doSomething() 方法。

常用的函数式接口

Java 8 提供了许多常用的函数式接口,可以在 java.util.function 包中找到。下面介绍几个最常用的函数式接口。

Consumer

Consumer 接口表示接收一个参数 T,没有返回值。常用于对接口进行一个操作,不需要返回结果,如输出信息、修改对象等。

Consumer printConsumer = System.out::println;
printConsumer.accept("Hello World!");

  

Supplier

Supplier 接口表示没有参数,返回一个结果 T。常用于获取接口的某个数值等操作。

Supplier helloSupplier = () -> "Hello World!";
System.out.println(helloSupplier.get());

  

Function

Function 接口表示接收一个参数 T,返回一个结果 R。常用于对接口进行一定的转换操作,如类型转换、字符串转换等。

Function strToInt = Integer::valueOf;
int result = strToInt.apply("5");
System.out.println(result);

  

Predicate

Predicate 接口表示接收一个参数 T,返回一个 boolean 类型的值。常用于对接口进行一个判断是否成立的操作,如校验、过滤等。

Predicate startsWithJ = (s) -> s.startsWith("J");
boolean result = startsWithJ.test("Java");
System.out.println(result);

  

Lambda表达式和方法引用

Lambda 表达式和方法引用是函数式接口的创建方式,也是函数式编程的核心。Lambda 表达式可以理解为是一种匿名函数,可以传递到变量或方法中。方法引用表示使用现有方法实现函数式接口。下面简要介绍 Lambda 表达式和方法引用。

Lambda表达式

Lambda 表达式定义如下:

(parameters) -> expression or statement block

可以分为以下几种形式:

  • 无参数:() -> expression
  • 一个参数:(p) -> expression
  • 多个参数:(p1, p2) -> expression or (p1, p2) -> { statement block }

示例:

Runnable r1 = () -> System.out.println("Hello World 1");

方法引用

方法引用是使用 :: 来表示的。

  • 对象引用:object::method
  • 静态方法引用:Class::method
  • 特定类的任意对象方法引用:Class::method
  • 构造函数引用:Class::new

示例:

Consumer printConsumer = System.out::println;

  

流和并行

Java 8 引入了流的概念(java.util.stream),在对集合进行操作时可以使用流来实现,可以使用多核处理器来加速计算。流的特点是能进行过滤、映射、排序、归约等复杂的操作,通过流式编程可以使代码更加简洁。

使用流时,可以选择串行流或并行流,前者适用于数据量小的情况,后者适用于数据量大的情况:

List list = Arrays.asList("a1", "a2", "b1", "c2", "c1");

//串行流
list.stream()
    .filter(s -> s.startsWith("c"))
    .map(String::toUpperCase)
    .sorted()
    .forEach(System.out::println);

//并行流
list.parallelStream()
    .filter(s -> s.startsWith("c"))
    .map(String::toUpperCase)
    .sorted()
    .forEach(System.out::println);

  

总结

本文介绍了 Java 8 函数式编程中最常用的函数式接口、Lambda 表达式和方法引用、流和并行。使用函数式接口可以使代码更加简洁,并且可以使用 Lambda 表达式和方法引用来创建函数式接口实例,使代码更加易于理解。流和并行是函数式编程的核心,可以使用流来实现复杂的操作并提高计算速度。