如何使用Java 8 Stream API将两个列表条件归约为双元素结果列表
Java 8 Stream 实现双列表按位对比计数
需求规则
对比两个列表的对应位置元素,按以下规则统计结果:
- 第一个列表对应位置元素更大时,结果第一位计数+1
- 第二个列表对应位置元素更大时,结果第二位计数+1
- 两元素相等时直接跳过,不做计数
- 两个列表长度不一致时,仅对比两者重叠索引位置的元素(即遍历到较短列表的末尾即停止)
已有Java 7实现逻辑如下:
int min = a.size() > b.size() ? b.size() : a.size(); List<Integer> result = Arrays.asList(0, 0); for(int i =0; i < min; i++) { if(a.get(i) > b.get(i)) result.set(0, result.get(0) + 1); else if(a.get(i) < b.get(i)) result.set(1, result.get(1) + 1); } return result;
目标是用Java 8 Stream API实现等价逻辑,避免拆分两个独立流做两次遍历。
最优实现方案
不需要拆分两次流遍历,直接通过IntStream生成索引序列,在收集阶段用可变容器同时维护两个计数即可,逻辑和原Java 7实现100%对齐,性能无额外损耗:
import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; public List<Integer> compareList(List<Integer> a, List<Integer> b) { int minLength = Math.min(a.size(), b.size()); return IntStream.range(0, minLength) .collect( // 初始化计数容器,初始值和原逻辑保持一致为[0,0] () -> Arrays.asList(0, 0), // 逐位对比累加计数 (result, idx) -> { int valA = a.get(idx); int valB = b.get(idx); if (valA > valB) { result.set(0, result.get(0) + 1); } else if (valA < valB) { result.set(1, result.get(1) + 1); } }, // 并行流执行时的分片结果合并规则 (res1, res2) -> { res1.set(0, res1.get(0) + res2.get(0)); res1.set(1, res1.get(1) + res2.get(1)); } ); }
实现说明
- 用
IntStream.range生成连续索引是Stream处理多集合按位操作的通用写法,规避了手动写for循环的模板代码 - 这里用的三参数
collect方法是Stream专门为多维度累加场景设计的,完全支持在单次遍历中同时维护多个计数,不需要事后做结果合并 - 第三个合并器参数即使日常用串行流也建议按规范写上,避免开启并行流时出现统计错误。
如果偏好更贴近函数式编程的写法,也可以用数组作为轻量累加容器实现,逻辑完全等价:
import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; public List<Integer> compareList(List<Integer> a, List<Integer> b) { int minLength = Math.min(a.size(), b.size()); int[] count = IntStream.range(0, minLength) .collect( () -> new int[2], (arr, idx) -> { int cmp = Integer.compare(a.get(idx), b.get(idx)); arr[0] += cmp > 0 ? 1 : 0; arr[1] += cmp < 0 ? 1 : 0; }, (arr1, arr2) -> { arr1[0] += arr2[0]; arr1[1] += arr2[1]; } ); return Arrays.asList(count[0], count[1]); }
实际开发优先选第一种写法,直接返回List类型结果,代码可读性更高,不需要额外做类型转换。
内容的提问来源于stack exchange,提问作者Gibbs
相关产品推荐
相关产品推荐

