如何让多段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,提问作者Володимир
相关产品推荐
相关产品推荐

