Java Stream API 是Java 8引入的一个重要特性,它为集合对象提供了函数式操作,使得对集合数据的处理变得高效且易于理解。Stream API 支持链式操作,允许以声明性的方式处理数据,而无需显式地写出迭代循环。以下是Java Stream API的几个关键点和使用示例:
Java Stream API简介
1.什么是Stream?
- Stream 不是集合,而是一种数据处理的抽象,它代表了可能的计算操作序列。Stream可以并行处理,充分利用多核处理器的优势。
2.Stream的两种类型
- 中间操作(Intermediate operations):这类操作会返回一个新的Stream,允许进一步的操作链式调用,如 filter, map。中间操作是延迟执行的。
- 终端操作(Terminal operations):这类操作会触发实际计算,产生结果或副作用,如 collect, forEach, count,执行后Stream不能再被使用。
3.优势
- 提高代码可读性和简洁性。
- 支持并行处理,提高性能。
- 函数式编程风格,易于理解和维护。
常用的Stream API方法
中间操作
- filter(Predicate): 过滤出满足条件的元素。
- map(Function): 对每个元素应用函数进行转换。
- sorted(Comparator): 对元素排序。
- distinct(): 去重,基于对象的equals和hashCode方法。
- peek(Consumer): 对每个元素执行操作并返回新的Stream(主要用于调试)。
终端操作
- collect(Collector): 将Stream转换为另一种形式,如列表、集合或聚合结果。
- forEach(Consumer): 对每个元素执行操作,无返回值。
- reduce(BinaryOperator): 将Stream元素累积成一个值,如求和、求最大值。
- anyMatch(Predicate): 检查是否至少有一个元素满足条件。
- allMatch(Predicate): 检查所有元素是否都满足条件。
- noneMatch(Predicate): 检查没有元素满足条件。
- findFirst(): 返回第一个元素的Optional。
- limit(long): 限制Stream中的元素数量。
- skip(long): 跳过Stream开始的N个元素。
使用示例
假设有一个Person对象列表,我们要找出年龄大于20岁的人的名字,并按字母顺序排序。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
class Person {
String name;
int age;
// 构造方法、getter和setter省略
}
public class StreamExample {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 22)
);
List<String> names = people.stream()
.filter(person -> person.getAge() > 20) // 过滤年龄大于20的
.map(Person::getName) // 提取名字
.sorted() // 排序
.collect(Collectors.toList()); // 收集到列表
System.out.println(names); // 输出:[Alice, Bob]
}
}
注意事项
- 在使用Stream时,应避免在中间操作中引入非功能性副作用,因为这可能会导致不可预测的行为。
- 终端操作执行后,Stream管道将关闭,不能再被重复使用。
- 并行Stream操作时,确保操作是线程安全的,特别是当操作影响外部状态时。