Java 函数式编程入门
长期以来,Java 一直与面向对象编程(OOP)紧密关联。然而,随着 2014 年 Java 8 的发布,该语言向函数式范式迈出了强有力的一步。Lambda 表达式、函数式接口和 Stream API 从根本上改变了编写代码的方式,使其更加简洁、可读且不易出错。
Java 中的函数式编程并非取代 OOP,而是强大的补充。它允许您编写声明式代码,在其中描述做什么,而不是如何做。在本文中,我们将分解关键概念,帮助您掌握 Java 的函数式风格,并展示实际示例。
1. Lambda 表达式和函数式接口
Java 函数式编程的基础是Lambda 表达式——这是一种实现匿名函数的紧凑方式。语法上,lambda 由参数列表、箭头(->)和主体组成:
(参数) -> { 主体 }Lambda 总是与函数式接口配对使用。函数式接口是只包含一个抽象方法的接口(例如,Runnable、Comparator、Predicate)。
实际示例:替换匿名类
让我们比较旧(OOP)和新(函数式)方法:
// 旧方法(匿名类)Runnable taskOld = new Runnable() { @Override public void run() { System.out.println("来自匿名类的问候!"); }};
// 新方法(lambda)Runnable taskNew = () -> System.out.println("来自 lambda 的问候!");
// 执行taskNew.run();如您所见,lambda 将代码从 6 行缩减到 1 行,同时保持了完整的功能。
内置函数式接口(java.util.function 包)
Java 提供了丰富的内置接口集。以下是四个主要接口:
Predicate<T>— 接受一个对象,返回boolean。用于过滤。Function<T, R>— 接受一种类型的对象,返回另一种类型的对象。用于转换。Consumer<T>— 接受一个对象,不返回任何内容(void)。用于副作用(如打印输出)。Supplier<T>— 不接受任何参数,返回一个对象。用于惰性数据生成。
Predicate 示例:
import java.util.function.Predicate;
public class Main { public static void main(String[] args) { Predicate<Integer> isEven = n -> n % 2 == 0; System.out.println(isEven.test(10)); // true System.out.println(isEven.test(7)); // false }}2. Stream API:以函数式风格处理集合
Stream API 是 Java 函数式编程的瑰宝。流(Stream)是一个支持顺序和并行操作的元素序列。主要优势:您不修改原始数据,而是创建新结果。
Stream API 由三个阶段构成:
- 创建流(从集合、数组或生成器)。
- 中间操作(过滤、排序、转换)。返回一个新的 Stream。
- 终端操作(收集结果、计数、查找)。结束流操作。
示例:列表的过滤和转换
假设我们有一个字符串列表,想要获取长度超过 3 个字符的字符串,将它们转换为大写并排序。
import java.u