目录

如何理解 Java 的函数式编程

以下部分代码内容由 ChatGPT 生成

定义和优势

函数式编程:将计算过程看作一系列函数的嵌套调用,而不是通过修改变量的值来实现计算,核心是函数嵌套调用

优势:代码简洁易读,通过避免共享状态和可变状态,可以更好地支持并发编程 (函数是无状态的,不会修改和依赖外部状态,只接受输入参数并返回结果,即使多个线程调用也不会相互影响)

在 Java 中的应用

在 Java 中通过:函数式接口 @FunctionalInterface 注解、lambda 表达式和方法引用、 Stream API、Optional 类,共同实现函数式编程

核心思想嵌套函数调用是通过 Stream API 实现,也就是 filter、mapToInt 等方法:

1
int sum = list.stream().filter(i -> i % 2 == 0).mapToInt(Integer::intValue).sum();

而函数式接口、lambda 表达式和方法引用是让函数的定义和传递更加简洁方便,是一种定义方法

Optional 类是避免空指针,在函数式编程中体现的是尽可能避免副作用,使代码更加健壮和安全

实例化函数式接口:

使用 @FunctionalInterface 注解定义在接口上,表示是函数式接口;只有一个抽象方法的接口都被认为是函数式接口

为什么要限制只有一个抽象方法:如果有多个方法,在通过 lambda 表达式和方法引用实例化时就无法确定使用那个方法

lambda 表达式和方法引用是对接口的实现,可以直接通过 lambda 表达式和方法引用创建接口实例,lambda 表达式和方法引用的入参和返回值需要和函数式接口中的方法保持一致

lambda 表达式实例化接口:

1
2
3
4
5
6
7
8
9
@FunctionalInterface
interface MyInterface {
    void doSomething();
}
 public static void main(String[] args) {
    // 使用 lambda 表达式实例化函数式接口
    MyInterface myInterface = () -> System.out.println("Lambda expression");
    myInterface.doSomething(); // 输出 "Lambda expression"
}

方法引用实例化接口:任何一个类中的方法和函数式接口中的方法具有相同的参数列表和返回类型时,就可以创建

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class MyClass {
    public static void doSomething() {
        System.out.println("Method reference");
    }
}
 public static void main(String[] args) {
    // 使用方法引用实例化函数式接口
    MyInterface myInterface = MyClass::doSomething;
    myInterface.doSomething(); // 输出 "Method reference"
}

Stream API:

Stream 中的 filter、mapToInt、map 等方法的入参都是函数式接口:

1
2
3
4
5
Stream<T> filter(Predicate<? super T> var1);

<R> Stream<R> map(Function<? super T, ? extends R> var1);

IntStream mapToInt(ToIntFunction<? super T> var1);

Java 编译器会自动把 lambda 表达式和方法引用编译成符合该方法入参格式的接口实例,