安全删除HashMap元素的唯一方式是使用迭代器remove()或Java 8+的removeIf();禁止在增强for或forEach中直接调用map.remove(),否则抛ConcurrentModificationException。

遍历时安全删除 HashMap 中的元素,核心原则只有一条:不能在增强 for 循环或 lambda 的 forEach 中直接调用 map.remove(key),否则必定触发 ConcurrentModificationException。唯一安全的方式是通过迭代器的 remove() 方法,或使用 Java 8+ 提供的 removeIf()。
用 Iterator 遍历并调 remove()(兼容所有 JDK 版本)
这是最通用、最可控的方式。必须从 entrySet().iterator() 获取迭代器,然后在循环中用 iterator.remove() 删除当前项:
- 每次调用
iterator.next()后,只能调一次iterator.remove(),且不能跳过或重复调用 - 不要在循环体里写
map.remove(entry.getKey()),这会破坏迭代器状态 - 示例:删除 value 小于 10 的键值对
while (it.hasNext()) {
Map.Entry<String, Integer> e = it.next();
if (e.getValue() < 10) {
it.remove(); // ✅ 安全
}
}
用 entrySet().removeIf()(Java 8+ 推荐)
语义清晰、代码简洁,底层仍基于迭代器,线程安全由方法内部保证:
- 参数是
Predicate<Map.Entry<K,V>>,可直接访问 key 和 value - 不支持中断或复杂控制流(比如 break),适合单条件批量删除
- 示例:删除所有 key 以 "temp" 开头的项
避免这些常见错误
以下写法都会抛出 ConcurrentModificationException:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
for (Map.Entry<K,V> e : map.entrySet()) { if (...) map.remove(e.getKey()); }map.entrySet().forEach(e -> { if (...) map.remove(e.getKey()); });-
for (K key : map.keySet()) { if (...) map.remove(key); }(除非是 ConcurrentHashMap)
原因:这些方式底层都依赖 fast-fail 迭代器,结构修改会立即检测并报错。
特殊场景:需要边遍历边更新 value
如果只是修改 value(不是删除),可以用 entry.setValue(newVal),这是允许的:
-
entry.setValue()不改变集合结构,不会触发检查 - 但禁止在同个 entry 上连续多次调用
setValue()后再调remove()—— 顺序混乱易出错 - 如需“先改再删”,建议拆成两步:先收集待删 key,遍历结束后统一删

















