遍历hashmap时修改键值对的核心原则是:不能直接改key,value可安全更新;改key须先删旧再加新;所有操作需避免concurrentmodificationexception。

遍历 HashMap 时修改键值对,核心原则是:**不能直接改 key,value 可安全更新;要改 key,必须先删旧、再加新;所有修改操作都需避开并发修改异常(ConcurrentModificationException)**。
修改 value:用 put 或 replace 最稳妥
遍历时更新 value 是常见需求,推荐以下两种方式:
- put(key, newValue):最常用。无论 key 是否存在,都会覆盖对应 value。语义清晰,线程不安全但单线程下无副作用。
-
replace(key, newValue):语义更明确——只在 key 存在时才替换,避免误插入。还可带旧值校验:
replace(key, oldValue, newValue),仅当当前值匹配 oldValue 才更新,适合条件更新场景。
修改 key:没有“重命名”操作,只能“删旧建新”
HashMap 不允许修改已存入的 key 对象(因 hash 值和桶位置依赖 key 的 hashCode 和 equals)。强行修改 key 内容(如可变对象)会导致后续 get 失败或数据丢失。正确做法是:
- 先用
map.remove(oldKey)删除原键值对; - 再用
map.put(newKey, value)插入新键值对; - 若遍历中执行此操作,必须用迭代器遍历 entrySet,并在 remove 后立即 put,否则可能跳过元素或触发异常。
遍历中安全修改的唯一可靠方式:用 Iterator 配合 entrySet
增强 for 循环(for-each)底层也是迭代器,但隐藏了 remove 方法,无法在循环中删除元素。要边遍历边改(尤其是删 key 或批量更新),必须显式使用 Iterator:
- 获取
Iterator<map.entry>> iter = map.entrySet().iterator();</map.entry> - 循环中调用
iter.next()获取当前 Entry; - 用
entry.getKey()和entry.getValue()读取原数据; - 根据逻辑决定是否
iter.remove(),再map.put(newKey, newValue); - 注意:
iter.remove()只能紧跟一次next()调用后使用,且每轮最多一次。
哪些操作要绝对避免
- 在增强 for 循环中调用
map.remove(key)或map.put(...)→ 触发 ConcurrentModificationException; - 用
keySet()遍历后反复调用map.get(key)再put(key, ...)→ 性能差,且仍面临并发修改风险; - 把可变对象(如 ArrayList、StringBuilder)作为 key 后修改其内容 → 破坏哈希一致性,导致 get/containsKey 失效;
- 用 Lambda 的
forEach修改 map → 不支持中途退出,也无法安全 remove,仅适合只读或纯计算场景。











