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下这两个值是一致的)。
- key:使用
额外建议
为了避免后续可能出现的问题,建议给ChargeType类重写equals和hashCode方法,基于serviceType和chargeTypeName来实现,这样在使用集合操作时能更准确地判断对象是否为同一类型。
内容的提问来源于stack exchange,提问作者poojay
相关产品推荐
相关产品推荐

