Java中的函数式编程:Lambda与Stream API实战
Java 8 引入了函数式编程的支持,主要通过 Lambda 表达式 和 Stream API 来实现。这些特性使得 Java 程序员能够以更简洁、更声明式的方式处理集合和数据流。下面我们将通过一些实战示例来深入理解 Lambda 表达式和 Stream API 的使用。
1. Lambda 表达式
Lambda 表达式是 Java 8 中引入的一种简洁的匿名函数表示方式。它可以用来替代匿名内部类,尤其是在函数式接口(只有一个抽象方法的接口)的场景下。
1.1 基本语法
(parameters) -> expression或(parameters) -> { statements; }
1.2 示例
假设我们有一个 List<String>
,我们想对每个元素执行某个操作:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 使用匿名内部类
names.forEach(new Consumer<String>() {@Overridepublic void accept(String name) {System.out.println(name);}
});// 使用 Lambda 表达式
names.forEach(name -> System.out.println(name));
2. Stream API
Stream API 提供了一种高效且易于使用的处理数据集合的方式。Stream 不是数据结构,而是一个来自数据源(如集合、数组等)的元素序列,支持聚合操作。
2.1 创建 Stream
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 从集合创建 Stream
Stream<String> stream = names.stream();// 从数组创建 Stream
String[] nameArray = {"Alice", "Bob", "Charlie"};
Stream<String> streamFromArray = Arrays.stream(nameArray);// 直接创建 Stream
Stream<String> streamOf = Stream.of("Alice", "Bob", "Charlie");
2.2 中间操作与终端操作
-
中间操作:返回一个新的 Stream,可以链式调用。常见的中间操作有
filter
,map
,sorted
等。 -
终端操作:触发 Stream 的处理并返回结果或副作用。常见的终端操作有
forEach
,collect
,reduce
等。
2.3 示例
2.3.1 过滤与映射
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 过滤出长度大于 3 的名字,并将其转换为大写
List<String> result = names.stream().filter(name -> name.length() > 3).map(String::toUpperCase).collect(Collectors.toList());System.out.println(result); // 输出: [ALICE, CHARLIE]
2.3.2 排序
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 按名字长度排序
List<String> sortedNames = names.stream().sorted((name1, name2) -> Integer.compare(name1.length(), name2.length())).collect(Collectors.toList());System.out.println(sortedNames); // 输出: [Bob, Alice, Charlie]
2.3.3 归约
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 计算所有数字的和
int sum = numbers.stream().reduce(0, (a, b) -> a + b);System.out.println(sum); // 输出: 15
2.3.4 收集
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 将名字收集到一个新的 List 中
List<String> collectedNames = names.stream().filter(name -> name.length() > 3).collect(Collectors.toList());System.out.println(collectedNames); // 输出: [Alice, Charlie]
2.3.5 并行流
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 使用并行流处理数据
List<String> parallelResult = names.parallelStream().filter(name -> name.length() > 3).map(String::toUpperCase).collect(Collectors.toList());System.out.println(parallelResult); // 输出: [ALICE, CHARLIE]
3. 综合示例
假设我们有一个 Person
类,我们想对一组 Person
对象进行一些操作:
class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return name + " (" + age + ")";}
}public class Main {public static void main(String[] args) {List<Person> people = Arrays.asList(new Person("Alice", 23),new Person("Bob", 30),new Person("Charlie", 17),new Person("David", 25));// 过滤出年龄大于 18 的人,并按年龄排序List<Person> adults = people.stream().filter(person -> person.getAge() > 18).sorted((p1, p2) -> Integer.compare(p1.getAge(), p2.getAge())).collect(Collectors.toList());System.out.println(adults); // 输出: [Alice (23), David (25), Bob (30)]}
}
4. 总结
-
Lambda 表达式 提供了一种简洁的方式来表示匿名函数,特别适用于函数式接口。
-
Stream API 提供了一种声明式的方式来处理集合和数据流,支持链式操作和并行处理。
通过结合 Lambda 表达式和 Stream API,Java 程序员可以编写出更简洁、更易读的代码,同时也能更好地利用多核处理器的并行计算能力。
Java 面试 高阶版 葵花宝典级(耗时两个月打造),持续更新 思维导图模板_ProcessOn思维导图、流程图