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

Java Stream分组聚合问题:按Service Type与Charge Type累计数据异常

问题排查与修正

问题根源

你当前代码的核心错误在于内层toMap的key选择错误:
你用了ChargeType::getServiceType作为内层Map的key,但在外层已经按serviceType分组的情况下,同一组内所有ChargeType对象的serviceType完全相同,导致内层Map的key全部重复,触发merge函数将所有记录合并为一个,最终每个serviceType下只剩一条数据。

正确实现方式

要实现「先按serviceType分组,再在组内按chargeTypeName聚合金额和数量」的需求,需将内层toMap的key改为ChargeType::getChargeTypeName,同时确保merge逻辑正确合并amount和quantity:

修正后的代码

Map<String, Map<String, ChargeType>> chargeTypeCol = chargeTypeList.stream()
    .collect(Collectors.groupingBy(
        ChargeType::getServiceType,
        LinkedHashMap::new, // 可选:保留分组顺序
        Collectors.toMap(
            ChargeType::getChargeTypeName, // 内层按chargeTypeName分组
            Function.identity(),
            (existing, newItem) -> new ChargeType(
                existing.getServiceType(), // 同一组serviceType一致,用existing或newItem都可
                existing.getChargeTypeName(), // 同一key下chargeTypeName一致
                existing.getAmount() + newItem.getAmount(),
                existing.getQuantity() + newItem.getQuantity()
            ),
            LinkedHashMap::new // 可选:保留chargeType顺序
        )
    ));
return chargeTypeCol;

代码说明

  • 外层groupingBy:按serviceType将数据分为不同的组,指定LinkedHashMap::new可保留分组的插入顺序。
  • 内层toMap:
    • key:使用ChargeType::getChargeTypeName,确保同一serviceType下不同chargeType的记录会被分到不同的key下。
    • merge函数:当同一chargeTypeName存在多条记录时,合并它们的amount和quantity,同时复用已有的serviceType和chargeTypeName(因为同一组/key下这两个值是一致的)。

额外建议

为了避免后续可能出现的问题,建议给ChargeType类重写equals和hashCode方法,基于serviceType和chargeTypeName来实现,这样在使用集合操作时能更准确地判断对象是否为同一类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:25:29