Java中Map的merge()方法通过一次哈希实现键存在性判断与值合并,支持自动put、函数合并或null删除,性能优、线程安全、语义清晰,适用于流式累加和复杂合并场景。

Java 中 Map 的 merge() 方法是处理键冲突和数据累加的简洁利器,它把“判断是否存在→取旧值→计算新值→写回”四步压缩成一行代码,天然支持流式(stream)场景,无需手动判空、避免并发问题,也比 toMap() 更灵活可控。
merge() 的核心逻辑:一次哈希,自动分流
调用 map.merge(key, value, remappingFunction) 时:
- 如果
key不存在,直接put(key, value) - 如果
key存在,用remappingFunction合并旧值与传入的value,结果非null则更新,为null则删除该键 - 整个过程只查一次哈希桶,性能优于先
get()再put()
流式累加:配合 forEach 或 collect 实现统计聚合
对集合做频次、金额、权重等累加,推荐用 forEach + merge,语义清晰、无中间 Map 初始化开销:
- 单词计数:
words.forEach(word -> countMap.merge(word, 1, Integer::sum)) - 金额汇总:
transactions.forEach(t -> amountMap.merge(t.getDept(), t.getAmount(), BigDecimal::add)) - 带默认权重的累加:
items.forEach(i -> scoreMap.merge(i.getUserId(), i.getWeight(), (old, w) -> old == null ? w : old + w))
替代 toMap 的 merge 场景:更安全、更可控
相比 Collectors.toMap(keyMapper, valueMapper, mergeFunc),merge() 在以下情况更优:
立即学习“Java免费学习笔记(深入)”;
- 需要复用已有 Map(如缓存、共享状态),而非新建
- 合并逻辑复杂,比如字符串拼接、取最大值、条件覆盖:
(old, newVal) -> old == null || newVal > old ? newVal : old - 需线程安全且原子执行:搭配
ConcurrentHashMap,merge()是原子操作,toMap的收集器则依赖并行流内部同步机制 - 允许删除键:当
remappingFunction返回null,自动移除该条目
注意事项:null 安全与类型一致性
merge() 不会主动拒绝 null 值,但不同 Map 实现有差异:
-
HashMap允许null值;ConcurrentHashMap不允许null键或值,否则抛NullPointerException - 确保
remappingFunction输入输出类型与 Map 声明一致,例如Map<String, BigDecimal>就不能用Integer::sum - 避免在函数中修改原对象(如直接 addAll 到旧 List),应返回新对象以保证不可变性与线程安全


















