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

Java使用Stream按Product的vat分组后统计各数值字段总和如何实现

解决方案

你可以通过自定义统计结果实体+Stream分组收集的方式实现需求,有两种常用实现方式如下:

第一步:定义统计结果实体

先新建TaxSummary类用来存储每个vat税率对应的三个字段总和:

public class TaxSummary {
    private double totalNetPrice;
    private double totalVatAmount;
    private double totalGrossPrice;

    // 累加单个商品的金额
    public void addProduct(Product product) {
        this.totalNetPrice += product.getNetPrice();
        this.totalVatAmount += product.getVatAmount();
        this.totalGrossPrice += product.getGrossPrice();
    }

    // 合并两个统计结果(并行流场景会用到)
    public TaxSummary merge(TaxSummary other) {
        this.totalNetPrice += other.totalNetPrice;
        this.totalVatAmount += other.totalVatAmount;
        this.totalGrossPrice += other.totalGrossPrice;
        return this;
    }

    @Override
    public String toString() {
        return "TaxSummary{" +
                "totalNetPrice=" + totalNetPrice +
                ", totalVatAmount=" + totalVatAmount +
                ", totalGrossPrice=" + totalGrossPrice +
                '}';
    }

    // 按需添加getter方法
}

第二步:修改业务方法

实现方式1:先分组再遍历统计(兼容性最好,Java 8+全版本支持,逻辑直观)

如果需要保留按vat分组后的Product列表,用这种方式:

public static Map<Double, TaxSummary> calculatingTaxes(List<Product> products){
    // 原有的按vat分组逻辑
    Map<Double, List<Product>> productTaxesMap = products.stream()
            .collect(Collectors.groupingBy(Product::getVat));

    // 遍历每个分组计算总和
    Map<Double, TaxSummary> summaryMap = new HashMap<>();
    productTaxesMap.forEach((vat, productList) -> {
        TaxSummary summary = new TaxSummary();
        productList.forEach(summary::addProduct);
        summaryMap.put(vat, summary);
    });

    // 测试输出结果
    summaryMap.forEach((vat, summary) -> System.out.printf("税率%.2f 统计结果:%s%n", vat, summary));
    return summaryMap;
}

实现方式2:下游收集器一步完成(性能更高,适合大数据量场景)

如果不需要保留分组后的Product列表,直接用自定义收集器一步统计:

public static Map<Double, TaxSummary> calculatingTaxes(List<Product> products){
    return products.stream()
            .collect(Collectors.groupingBy(
                    Product::getVat,
                    Collector.of(
                            TaxSummary::new,
                            TaxSummary::addProduct,
                            TaxSummary::merge
                    )
            ));
}

运行结果

对你给出的测试数据,输出结果如下:

税率1.00 统计结果:TaxSummary{totalNetPrice=200.0, totalVatAmount=0.0, totalGrossPrice=200.0}
税率1.23 统计结果:TaxSummary{totalNetPrice=300.0, totalVatAmount=69.0, totalGrossPrice=369.0}
税率1.08 统计结果:TaxSummary{totalNetPrice=200.0, totalVatAmount=16.0, totalGrossPrice=216.0}

注意事项

  • 生产环境用double存储金额会有精度丢失风险,建议替换为BigDecimal类型
  • 如果需要同时返回分组后的Product列表和统计结果,自定义实体将List<Product>和TaxSummary组合即可

内容的提问来源于stack exchange,提问作者Jakub Kołacz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 19:15:04