1. 概述
在 Java Stream 开发中,高效处理和转换数据是写出优质代码的关键。处理连续元素时,使用 SimpleEntry 进行简单配对和利用有状态转换处理动态场景,是两种强有力的技术。
本教程将探讨如何利用 SimpleEntry 创建相邻元素对,以及有状态转换如何提供灵活的数据流处理方案。让我们深入探索这些方法如何优化 Java Stream 操作。
2. 问题定义
给定一个元素流,我们需要创建一个包含连续元素对的列表。例如,对于整数流 *[1, 2, 3, 4, 5]*,期望输出配对结果 *[(1, 2), (2, 3), (3, 4), (4, 5)]*。
接下来看具体实现方案。
3. 解决方案
根据不同需求和约束条件,收集流中连续元素对有多种实现方式。这里介绍两种常用方法:
3.1. 收集为 List
核心思路是先将流元素收集到列表中,通过索引访问实现配对操作。 这种方法简单直接,适合大多数场景。
public static <T> List<SimpleEntry<T, T>> collectSuccessivePairs(Stream<T> stream) {
List<T> list = stream.collect(Collectors.toList());
return IntStream.range(0, list.size() - 1)
.mapToObj(i -> new SimpleEntry<>(list.get(i), list.get(i + 1))).collect(Collectors.toList());
}
实现要点:
- ✅ 使用
Collectors.toList()
将流元素转为列表 - ✅ 通过
IntStream.range(0, list.size() - 1)
生成有效索引(注意排除末尾元素) - ✅ 用
SimpleEntry
包装相邻元素对 - ✅ 最终收集为新列表
时间复杂度分析:
- 流转列表:O(n)
- 元素配对:O(n)
- 总体时间复杂度:O(n)
空间复杂度分析:
- 元素存储:O(n)
- 结果列表:O(n)
- 总体空间复杂度:O(n)
3.2. 收集为 List<List>
这种方法将连续元素对存储为嵌套列表结构,适合需要灵活处理元素对的场景:
public static <T> Stream<List<T>> pairwise(Stream<T> stream) {
List<T> list = stream.collect(Collectors.toList());
List<List<T>> pairs = new ArrayList<>();
for (int i = 0; i < list.size() - 1; i++) {
pairs.add(Arrays.asList(list.get(i), list.get(i + 1)));
}
return pairs.stream();
}
关键步骤:
- ✅ 流元素收集到列表(保证随机访问)
- ✅ 循环遍历到倒数第二个元素
- ✅ 用
Arrays.asList()
创建相邻元素对 - ✅ 返回新流(支持后续链式操作)
⚠️ 注意:此方法返回的是 Stream<List<T>>
而非直接列表,保留了流操作的灵活性。
复杂度分析:
- 时间复杂度:O(n)(收集+配对)
- 空间复杂度:O(n)(元素存储+结果存储)
- 与 SimpleEntry 方案复杂度相同,但数据结构更灵活
4. 总结
本文探讨了在 Java Stream 中处理连续元素对的两种核心方法:
- SimpleEntry 方案:简洁高效,适合固定配对场景
- List<List
> 方案:灵活可扩展,适合复杂处理流程
两种方法各有优势:
- ✅ 时间复杂度均为 O(n)
- ✅ 空间复杂度均为 O(n)
- ✅ 实现简单直观
- ⚠️ 需注意中间存储开销(不适合超大流)
实际开发中,根据具体需求选择即可。对于简单配对场景,SimpleEntry 更轻量;需要后续流操作时,List<List
所有示例代码已上传至 GitHub 仓库,欢迎参考实践。