You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:01:11