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

如何让多段Java Stream赋值代码更简洁紧凑?

简化重复Stream遍历的方案

你可以通过单次Stream遍历完成三个价格总和的计算,避免重复遍历items集合,下面提供几种实用的实现方式:

方案1:使用数组作为累加容器(无需额外类)

直接利用BigDecimal数组存储三个总和,通过reduce完成单次遍历的累加:

BigDecimal[] totals = items.stream()
    .reduce(
        // 初始值:三个ZERO组成的数组
        new BigDecimal[]{ZERO, ZERO, ZERO},
        // 累加器:处理每个item,更新三个总和
        (acc, item) -> new BigDecimal[]{
            acc[0].add(item.getTotalPrice1()),
            acc[1].add(item.getTotalPrice2()),
            acc[2].add(item.getTotalPrice3())
        },
        // 组合器:并行流场景下合并两个数组的结果
        (left, right) -> new BigDecimal[]{
            left[0].add(right[0]),
            left[1].add(right[1]),
            left[2].add(right[2])
        }
    );

batchPrice1 = totals[0];
batchPrice2 = totals[1];
batchPrice3 = totals[2];

方案2:自定义POJO存储总和(可读性更高)

如果觉得数组不够直观,可以定义一个简单的POJO来封装三个价格总和,代码可读性更强:

// 自定义总和容器类
class PriceTotals {
    private BigDecimal total1 = ZERO;
    private BigDecimal total2 = ZERO;
    private BigDecimal total3 = ZERO;

    // 处理单个item,累加价格
    public PriceTotals accumulate(CommodityItem item) {
        total1 = total1.add(item.getTotalPrice1());
        total2 = total2.add(item.getTotalPrice2());
        total3 = total3.add(item.getTotalPrice3());
        return this;
    }

    // 合并两个总和容器(并行流场景使用)
    public PriceTotals combine(PriceTotals other) {
        total1 = total1.add(other.total1);
        total2 = total2.add(other.total2);
        total3 = total3.add(other.total3);
        return this;
    }
}

使用时只需一次Stream遍历:

PriceTotals totals = items.stream()
    .reduce(new PriceTotals(), PriceTotals::accumulate, PriceTotals::combine);

batchPrice1 = totals.total1;
batchPrice2 = totals.total2;
batchPrice3 = totals.total3;

方案3:使用Collectors.teeing(Java 12+)

如果你的项目使用Java 12及以上版本,可以利用Collectors.teeing同时执行多个收集操作,通过嵌套实现三个总和的收集:

BigDecimal[] totals = items.stream()
    .collect(Collectors.teeing(
        // 先收集前两个总和
        Collectors.teeing(
            Collectors.reducing(ZERO, CommodityItem::getTotalPrice1, BigDecimal::add),
            Collectors.reducing(ZERO, CommodityItem::getTotalPrice2, BigDecimal::add),
            (t1, t2) -> new BigDecimal[]{t1, t2}
        ),
        // 收集第三个总和
        Collectors.reducing(ZERO, CommodityItem::getTotalPrice3, BigDecimal::add),
        // 合并三个结果
        (arr, t3) -> new BigDecimal[]{arr[0], arr[1], t3}
    ));

batchPrice1 = totals[0];
batchPrice2 = totals[1];
batchPrice3 = totals[2];

方案选择建议

  • 如果是Java 8环境,优先选择方案1或方案2,无需依赖高版本API;
  • 如果追求代码可读性且字段较多,方案2更合适;
  • Java 12+环境下,teeing可以实现更简洁的收集逻辑,但字段过多时嵌套会显得繁琐。

以上所有方案都只需要遍历一次items集合,相比原代码的三次遍历,在数据量较大时能明显提升性能。

内容的提问来源于stack exchange,提问作者Володимир

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 03:55:25