Java函数式编程:从A到Z
函数式编程(FP)是一种编程范式,将计算视为数学函数的求值,避免状态改变和可变数据。Java传统上是一种命令式语言,但从版本8开始积极引入FP元素。这使得编写更简洁、可预测且易于测试的代码成为可能,尤其是在处理集合和异步操作时。
在本文中,我们将探讨Java中FP的核心概念:从Lambda表达式到Stream API和Optional的高级技术。您将学习如何在实际中应用这些工具,使您的代码更清晰、更高效。
1. 基础:Lambda表达式和函数式接口
Lambda表达式是匿名方法(函数)的简洁表示形式。它允许将行为作为数据传递。语法:(参数) -> 主体。
函数式接口是只有一个抽象方法(SAM——单一抽象方法)的接口。这类接口可以通过Lambda实现。java.util.function中的关键内置接口:
Predicate<T>— 接受T类型对象,返回boolean(方法test)。Function<T, R>— 接受T,返回R(方法apply)。Consumer<T>— 接受T,不返回任何内容(方法accept)。Supplier<T>— 不接受任何参数,返回T(方法get)。UnaryOperator<T>— Function的特例,其中T和R类型相同。
示例:使用Comparator(函数式接口)对列表排序
import java.util.*;
public class LambdaExample { public static void main(String[] args) { List<String> names = Arrays.asList("伊万", "安娜", "彼得", "玛丽亚");
// 不使用Lambda(匿名类) Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return a.length() - b.length(); } });
// 使用Lambda Collections.sort(names, (a, b) -> a.length() - b.length());
// 更简洁:使用Comparator.comparingInt names.sort(Comparator.comparingInt(String::length));
System.out.println(names); // [安娜, 彼得, 伊万, 玛丽亚] }}示例:使用Predicate进行过滤
import java.util.function.Predicate;
public class PredicateExample { public static void main(String[] args) { Predicate<Integer> isEven = n -> n % 2 == 0; Predicate<Integer> isPositive = n -> n > 0;
System.out.println(isEven.test(4)); // true System.out.println(isEven.and(isPositive).test(-2)); // false(不是正数) System.out.println(isEven.or(isPositive).test(-3)); // true(不是偶数,但是正数?不,-3不是正数) }}2. Stream API:强大的数据处理工具
Stream API是一个元素序列,支持并行和串行操作。Stream不存储数据,而是转换数据。关键操作分为中间操作(返回新的Stream)和终端操作(结束处理并返回结果或副作用)。
Stream API的主要操作:
- 中间操作:
filter,map,flatMap,sorted,distinct,peek,limit,skip。 - 终端操作:
collec