一、Stream 的基础概念
-
定义与特性
- Stream 是单向数据流,对集合或数组进行高效处理,不存储数据,而是通过操作链生成新 Stream。
- 不可变性:原始数据源不被修改,所有操作均返回新 Stream。
- 延迟执行:中间操作(如
filter
)不会立即执行,需终端操作(如collect
)触发计算。
-
核心优势
- 简洁性:通过链式调用简化复杂逻辑(如
map
+filter
)。 - 高效性:支持并行处理(
parallelStream()
),充分利用多核性能。 - 灵活性:提供丰富的操作符(如
flatMap
处理嵌套集合)。
- 简洁性:通过链式调用简化复杂逻辑(如
二、Stream 的创建方式
-
从集合/数组创建
List list = Arrays.asList("Java", "Python", "C++"); Stream listStream = list.stream(); // 集合转Stream Stream arrayStream = Arrays.stream(new String[]{"A", "B"}); // 数组转Stream
-
其他创建方式
- 空 Stream:
Stream.empty()
(避免返回null
)。 - 构造器:
Stream.builder().add("A").build()
。 - 生成器:
Stream generated = Stream.generate(() -> "data").limit(5); // 无限流截断 Stream iterated = Stream.iterate(1, n -> n + 1).limit(10); // 递增生成
- 空 Stream:
三、Stream 的核心操作分类
1. 中间操作(Intermediate Operations)
操作 | 作用 | 示例代码 |
---|---|---|
filter | 筛选元素 | list.stream().filter(s -> s.length() > 3) // 筛选长度>3的字符串 |
map | 转换元素类型或值 | .map(String::toUpperCase) // 转换为大写 |
sorted | 排序 | .sorted(Comparator.naturalOrder()) // 自然排序 |
flatMap | 扁平化嵌套集合 | List> nestedList; nestedList.stream().flatMap(List::stream) |
distinct | 去重 | .distinct() // 基于 equals() 去重 |
2. 终端操作(Terminal Operations)
操作 | 作用 | 示例代码 |
---|---|---|
collect | 收集结果为集合或对象 | .collect(Collectors.toList()) // 转为List |
reduce | 归约操作(求和、拼接等) | Stream.of(1,2,3).reduce(0, Integer::sum) // 结果为6 |
forEach | 遍历元素 | .forEach(System.out::println) // 打印所有元素 |
count | 统计元素数量 | .count() // 返回Long类型总数 |
四、实战场景与示例
-
数据筛选与转换
List员工列表 = ...; List names = 员工列表.stream().filter(e -> e.getAge() > 30).map(E员工::getName).collect(Collectors.toList()); // 筛选年龄>30的员工姓名
-
分组统计
Map groupedByDep = 员工列表.stream().collect(Collectors.groupingBy(E员工::getDepartment)); // 按部门分组
-
双列集合处理
Map map = new HashMap<>(); Stream> entryStream = map.entrySet().stream();
五、进阶特性与注意事项
-
并行流(Parallel Streams)
- 通过
parallelStream()
启用多线程处理,适用于大数据量场景。 - 注意线程安全问题,避免非线程安全集合(如
ArrayList
)的并发修改。
- 通过
-
基本类型专用流
IntStream
、LongStream
、DoubleStream
优化内存和性能,避免自动装箱开销:IntStream.range(1, 100).sum(); // 计算1-99的和
-
避免常见错误
- 多次使用终端操作:Stream 一旦被终端操作消费,不可复用。
- 无限流处理:需结合
limit()
截断,防止内存溢出。
六、总结
Java Stream API 通过函数式编程范式,显著提升了集合操作的简洁性和性能。合理使用 map
、filter
、collect
等操作,结合并行流和基本类型流优化,可高效处理复杂数据场景。开发者需注意流的生命周期和线程安全,以充分发挥其优势。