Map.remove(key) 仅当 key 存在时返回被移除值,否则返回 null;put(key, value) 总是返回替换前的旧值,key 不存在时也返回 null;二者均因允许 null 值而使 null 返回值含义模糊,需用 containsKey 或 computeIfPresent 等安全方式判断存在性。

Java 中 Map.remove(key) 和 Map.put(key, value) 都可能返回旧值,但它们的触发条件、语义和使用场景完全不同。混淆二者行为容易导致逻辑错误或空指针异常。
remove 方法何时返回旧值
remove(Object key) 只有在指定 key 存在于 map 中时,才返回被移除的 value;否则返回 null。注意:返回 null 并不必然表示 key 不存在——当 map 允许 null 值(如 HashMap)且该 key 显式映射到 null 时,也会返回 null。
判断 key 是否真实存在,不能仅靠 remove 返回值是否为 null,应先用 containsKey 或结合 get + computeIfPresent 等更安全的方式确认。
put 方法返回旧值的含义
put(K key, V value) 总是返回与 key 关联的前一个 value(即替换前的值),如果 key 之前不存在,则返回 null。同样受 null 值干扰:若旧值就是 null,返回 null 不代表 key 未命中。
立即学习“Java免费学习笔记(深入)”;
常见误用是把 put 返回值当作“插入成功与否”的标志,其实它只反映“是否有旧值被覆盖”,而非“是否新增了条目”。需要区分新增/更新,建议改用 putIfAbsent 或 computeIfAbsent。
联动诊断的关键陷阱
当代码中连续调用 remove 后又 put(例如实现“原子替换”逻辑),需警惕以下问题:
- 两次操作非原子:中间可能被其他线程修改,导致状态不一致
- 对 null 的歧义处理:两个方法都返回 null,但原因不同,直接链式判断易出错
- ConcurrentHashMap 的特殊性:其
remove和put虽线程安全,但组合使用仍不保证原子性;应优先使用replace(K, V, V)或compute系列方法
更安全的替代写法
避免手动联动 remove+put,推荐以下方式:
- 替换值且需旧值:用
replace(K key, V newValue)—— 仅当 key 存在时替换,并返回旧值 - 条件替换:用
replace(K key, V oldValue, V newValue)—— 类似 CAS,避免竞态 - 统一更新逻辑:用
compute(K key, BiFunction super K, ? super V, ? extends V> remappingFunction),函数内可自由决定保留、修改或删除 - 插入或更新分离:用
putIfAbsent(仅插入)或merge(存在则合并)代替手写分支
理解返回值背后的契约比记住“返回什么”更重要。重点不是值本身,而是这个返回值所承诺的状态前提。


















