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

Java中如何通过Stream API一次计算对象列表多字段总和?

单次Stream调用计算多字段总和

我有一个包含X2、X3等整数字段的对象列表,示例代码如下(注:实际项目中需自定义包含X1/X2/X3字段的实体类,此处用MyObject代替原生Object):

List<MyObject> objectList = new ArrayList<>();
objectList.add(new MyObject("ABC", 1, 3));
objectList.add(new MyObject("XYZ", 2, 7));
objectList.add(new MyObject("AC", 1, 3));
objectList.add(new MyObject("AB", 1, 3));

需求是遍历该列表,计算所有对象的X2字段总和与X3字段总和。目前我通过两次Stream调用实现:

int X2Sum = objectList.stream().mapToInt(o -> o.getX2()).sum();
int X3Sum = objectList.stream().mapToInt(o -> o.getX3()).sum();

但希望能通过一次Stream调用完成计算,减少遍历次数。


可行实现方案

方案1:自定义容器类存储总和

定义一个简单的类来同时保存X2和X3的累加结果,通过reduce方法完成单次遍历:

// 自定义总和容器类
class SumHolder {
    private int x2Sum;
    private int x3Sum;

    public SumHolder(int x2Sum, int x3Sum) {
        this.x2Sum = x2Sum;
        this.x3Sum = x3Sum;
    }

    // 累加当前对象的X2、X3值
    public SumHolder accumulate(MyObject obj) {
        return new SumHolder(this.x2Sum + obj.getX2(), this.x3Sum + obj.getX3());
    }

    // 合并两个容器的结果(并行流场景必须实现)
    public SumHolder combine(SumHolder other) {
        return new SumHolder(this.x2Sum + other.x2Sum, this.x3Sum + other.x3Sum);
    }

    // Getter方法
    public int getX2Sum() { return x2Sum; }
    public int getX3Sum() { return x3Sum; }
}

// 单次Stream调用计算
SumHolder totalSum = objectList.stream()
    .reduce(new SumHolder(0, 0), SumHolder::accumulate, SumHolder::combine);

int x2Total = totalSum.getX2Sum(); // 计算结果:5
int x3Total = totalSum.getX3Sum(); // 计算结果:16

方案2:使用数组作为临时容器

如果不想额外定义类,可用长度为2的数组存储两个总和,代码更简洁:

int[] sums = objectList.stream()
    .reduce(new int[]{0, 0},
            (acc, obj) -> new int[]{acc[0] + obj.getX2(), acc[1] + obj.getX3()},
            (arr1, arr2) -> new int[]{arr1[0] + arr2[0], arr1[1] + arr2[1]});

int x2Sum = sums[0]; // 5
int x3Sum = sums[1]; // 16

方案3:单线程场景用forEach直接累加

如果确定是单线程环境,也可以直接用forEach完成单次遍历,但这种方式不支持并行流:

int x2Sum = 0;
int x3Sum = 0;
objectList.stream().forEach(obj -> {
    x2Sum += obj.getX2();
    x3Sum += obj.getX3();
});

注:如果用lambda修改外部局部变量,需将变量声明为final或等效的有效final(Java 8+支持),或者改用AtomicInteger,但后者在并行流中性能不如前两种方案。


关键说明

  • 前两种方案通过reduce实现,既支持单线程也支持并行流,避免了两次遍历的性能开销,数据量越大优势越明显。
  • 并行流场景下,reduce的第三个合并参数必须正确实现,否则会出现计算错误。

内容的提问来源于stack exchange,提问作者Chirag Jain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:40:37