merge() 将键冲突处理逻辑封装为函数,替代冗长的if+get+put,支持计数累加、字符串拼接、取优、清理等场景,配合ConcurrentHashMap实现线程安全的原子合并。

用 merge() 处理键冲突,核心是把“键存在时怎么合”这个业务判断,直接封装进一个函数里,而不是靠 if 判断 + get + put 拆成三步。它天然适配统计、拼接、取优、清理等常见逻辑,写法简洁且线程安全(配合 ConcurrentHashMap)。
计数累加:一行替代判空+取值+加法
传统方式要先 get(key),判是否为 null,再加 1,最后 put(key, newValue)——重复读、易漏判空、并发不安全。
用 merge() 只需:
-
countMap.merge("user_123", 1, Integer::sum)→ 首次插入 1,再次出现就 +1 -
amountMap.merge("dept_finance", BigDecimal.valueOf(1200.5), BigDecimal::add)→ 用不可变类型防浮点误差 - 若初始值不是 1(比如按权重叠加),可写:
merge(key, weight, (old, w) -> old == null ? w : old + w)
字符串拼接与字段合并:保留旧值、追加新值
不是覆盖,而是有选择地融合。关键在第三个参数的 BiFunction 怎么写:
- 追加非空标签:
(old, newVal) -> old == null ? newVal : old + "," + newVal - 只保留非空旧值:
(old, newVal) -> old != null ? old : newVal - 对象字段合并(如 User):
(old, newVal) -> old == null ? newVal : old.merge(newVal)(前提是对象提供merge()方法)
按规则取优或主动清理:返回 null 即删除
merge() 的合并函数返回 null,会自动触发 remove(key),适合条件性清理:
- 记录最高分:
(old, newVal) -> Math.max(old, newVal) - 超阈值后清空该键:
(old, newVal) -> old > 100 ? null : old + newVal - 以旧值为准(跳过更新):
(old, newVal) -> old
并发安全合并:ConcurrentHashMap + merge 是原子操作
HashMap.merge() 简化逻辑但不保线程安全;换成 ConcurrentHashMap 后,merge() 底层用 CAS 或锁保障「查-算-存」一步完成,彻底避免多线程计数丢失。
注意两点:
-
ConcurrentHashMap不接受null的 key 或 value,传入直接抛NullPointerException - 业务中可能含
null值,应提前过滤(如stream().filter(Objects::nonNull)),或改用compute()


















