摘要:Java Stream API 是 Java 8 引入的核心特性之一,用于以声明式、函数式风格处理集合数据。它支持链式操作和并行处理,极大简化了集合操作代码。以下是 Stream API 的全面解析:
Java Stream API 详解
Java Stream API 是 Java 8 引入的核心特性之一,用于以声明式、函数式风格处理集合数据。它支持链式操作和并行处理,极大简化了集合操作代码。以下是 Stream API 的全面解析:
一、Stream 的特点
声明式编程:通过方法链描述“做什么”,而非具体实现。惰性求值:中间操作(如 filter)不会立即执行,直到终端操作触发。不可变性:每次操作生成新流,不修改原始数据源。支持并行:通过 parallelStream 自动并行处理数据。二、创建 Stream 的方式
集合创建:java
List list = Arrays.asList("a", "b", "c");
Stream stream = list.stream;
数组创建:java
String array = {"a", "b", "c"};
Stream stream = Arrays.stream(array);
静态工厂方法:java
Stream stream = Stream.of("a", "b", "c"); // 直接生成
Stream infiniteStream = Stream.iterate(0, n -> n + 1); // 无限流
Stream randomStream = Stream.generate(Math::random); // 生成流
三、中间操作(Intermediate Operations)
中间操作返回新流,支持链式调用,常见操作包括:
过滤:java
stream.filter(s -> s.startsWith("A")); // 过滤以A开头的元素
映射:java
stream.map(String::toUpperCase); // 转为大写
stream.flatMap(line -> Arrays.stream(line.split(" "))); // 扁平化(拆分单词)
去重与限制:java
stream.distinct; // 去重
stream.limit(5); // 取前5个元素
stream.skip(2); // 跳过前2个元素
排序:java
stream.sorted; // 自然排序
stream.sorted((a, b) -> b.compareTo(a)); // 自定义排序(逆序)
四、终端操作(Terminal Operations)
终端操作触发实际计算,返回非流结果,常见操作包括:
遍历与收集:java
stream.forEach(System.out::println); // 遍历输出
List list = stream.collect(Collectors.toList); // 转为List
聚合计算:java
long count = stream.count; // 元素总数
Optional first = stream.findFirst; // 第一个元素
Optional any = stream.findAny; // 任意元素(并行时高效)
匹配检查:java
boolean allMatch = stream.allMatch(s -> s.length > 3); // 所有元素满足条件?
boolean anyMatch = stream.anyMatch(s -> s.contains("x")); // 存在元素满足条件?
归约操作:java
Optional sum = stream.reduce(Integer::sum); // 求和
Integer sum = stream.reduce(0, (a, b) -> a + b); // 初始值为0的求和
数值流特化:java
IntStream intStream = stream.mapToInt(Integer::parseInt); // 转为IntStream
int sum = intStream.sum; // 直接求和(效率高于reduce)
五、并行流(Parallel Stream)
通过并行处理提升大数据集处理效率:
java
List result = list.parallelStream
.filter(s -> s.length > 3)
.collect(Collectors.toList);
注意事项:
避免共享可变状态(如外部变量修改),防止线程安全问题。数据量大时效果显著,小数据可能适得其反。某些操作(如 limit、findFirst)在并行流中性能可能下降。六、注意事项
流不可复用:终端操作后流关闭,再次使用会抛出 IllegalStateException。避免副作用:操作应无状态,不依赖或修改外部变量。java
// 错误示例:修改外部列表
List output = new ArrayList;
stream.forEach(s -> output.add(s)); // 可能引发并发问题
// 正确方式:使用collect
List output = stream.collect(Collectors.toList);
正确选择并行流:考虑数据规模、操作开销和线程协调成本。七、代码示例
示例1:过滤、映射、收集
java
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List squares = numbers.stream
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.collect(Collectors.toList);
// 结果:[4, 16]
示例2:分组统计
java
Map> peopleByCity = persons.stream
.collect(Collectors.groupingBy(Person::getCity));
示例3:归约求和
java
int total = IntStream.range(1, 100)
.parallel
.sum; // 计算1到99的和
八、总结
优势:代码简洁、易读,支持复杂数据处理和并行化。适用场景:集合数据过滤、转换、聚合等操作。慎用场景:简单遍历或需直接修改集合时,传统循环可能更高效。Stream API 提升了 Java 对数据处理的抽象能力,合理使用可显著提升代码质量与性能。建议结合具体场景选择操作类型(中间/终端)及是否并行化。
来源:老客数据一点号