如何按Key分组HashMap元素并求和值?基于PartNatureDon模型实现
需求
需要按NatureDon对HashMap中的项进行分组,对重复项的金额求和,并将结果保存到PartNatureDon模型中。
实体类定义
public class PartNatureDon extends BaseEntity{ @ManyToOne @JoinColumn(name = "nature_don_col_id", nullable = false) private NatureDon natureDon; @ManyToOne @JoinColumn(name = "assistance_col_id", nullable = false) private Assistance assistance; @Column private double montant; }
现有代码(存在逻辑问题)
public void savePartNatureDon(){ PartNatureDon partNatureDon = new PartNatureDon(); Set<Don> dons = selected.getDons(); List<NatureDon> natureDonList = new ArrayList<>(); for (Don don : dons){ partNatureDon.setAssistance(don.getAssistance()); List<NatureDon> natureDons = don.getNatureDonList(); HashMap<String, Double> montant = new HashMap<>(); for (NatureDon natureDon : natureDons){ if (!natureDonList.stream().anyMatch(n->n.getLibelle().equals(natureDon.getLibelle()))) { natureDonList.add(natureDon); natureDonList.forEach (natureDon1 -> { montant.putIfAbsent(natureDon1.getLibelle(), Double.valueOf(don.getMontantNatureDon().get(natureDon1.getLibelle()))); montant.computeIfPresent(natureDon1.getLibelle(), (n, nature) -> Double.valueOf(nature + don.getMontantNatureDon().get(natureDon1.getLibelle()))); }); } } } }
修正后的实现方案
现有代码存在逻辑混乱(如每次循环新建HashMap、重复遍历列表、未实现最终保存逻辑),以下是更简洁高效的实现,利用Java 8+ Stream API完成分组求和:
// 假设你已注入JPA Repository用于保存PartNatureDon @Autowired private PartNatureDonRepository partNatureDonRepository; public void savePartNatureDon(){ Set<Don> dons = selected.getDons(); // 1. 按「Assistance + NatureDon」分组,累加对应金额 Map<Assistance, Map<NatureDon, Double>> groupedData = dons.stream() .flatMap(don -> don.getNatureDonList().stream() .map(natureDon -> new AbstractMap.SimpleEntry<>( // 构建分组键:Assistance + NatureDon new AbstractMap.SimpleEntry<>(don.getAssistance(), natureDon), // 获取当前Don中该NatureDon的金额 don.getMontantNatureDon().get(natureDon.getLibelle()) )) ) .collect(Collectors.groupingBy( entry -> entry.getKey().getKey(), // 外层按Assistance分组 Collectors.groupingBy( entry -> entry.getKey().getValue(), // 内层按NatureDon分组 Collectors.summingDouble(Map.Entry::getValue) // 求和金额 ) )); // 2. 将分组结果转换为PartNatureDon实体并保存 List<PartNatureDon> partNatureDons = new ArrayList<>(); groupedData.forEach((assistance, natureDonAmountMap) -> { natureDonAmountMap.forEach((natureDon, totalMontant) -> { PartNatureDon entity = new PartNatureDon(); entity.setAssistance(assistance); entity.setNatureDon(natureDon); entity.setMontant(totalMontant); partNatureDons.add(entity); }); }); // 批量保存到数据库 partNatureDonRepository.saveAll(partNatureDons); }
实现说明
- 分组逻辑:通过嵌套分组,先按
Assistance分组,再按NatureDon分组,同时用summingDouble自动累加同一分组下的金额。 - 数据转换:遍历分组后的结果,为每个「Assistance + NatureDon」组合创建
PartNatureDon实体,设置对应的总金额。 - 批量保存:使用
saveAll批量插入,提升数据库操作效率。
内容的提问来源于stack exchange,提问作者Krah Landry Koffi
相关产品推荐
相关产品推荐

