必须通过迭代器的remove()或removeif()删除map元素,否则抛concurrentmodificationexception;推荐entryset().iterator()显式删除或java 8+的removeif()批量过滤,多线程场景优先用concurrenthashmap。

不能在增强 for 循环或直接调用 map.remove() 时删除元素,否则会抛出 ConcurrentModificationException。核心原则是:**必须通过迭代器的 remove() 方法,或使用 Java 8+ 的 removeIf() 等线程安全的批量操作**。
用 entrySet().iterator() 显式删除(最通用)
适用于所有标准 Map 实现(HashMap、LinkedHashMap、TreeMap),逻辑清晰、兼容性好。
- 调用
map.entrySet().iterator()获取Iterator<map.entry>></map.entry> - 在
while(it.hasNext())循环中用it.next()取出当前条目 - 满足条件时,立即调用
it.remove()——这是唯一被允许的删除方式
示例:删掉 value 为 null 或 0 的键值对
Mapmap.put("a", 1); map.put("b", null); map.put("c", 0);
Iterator
while (it.hasNext()) {
Map.Entry
if (e.getValue() == null || e.getValue() == 0) {
it.remove(); // ✅ 安全
}
}
用 removeIf() 批量过滤(推荐 Java 8+)
代码更简洁,语义明确,底层仍基于迭代器,无需手动管理循环逻辑。
-
map.keySet().removeIf(k -> k.startsWith("tmp")):按 key 删除 -
map.values().removeIf(Objects::isNull):按 value 删除 map.entrySet().removeIf(e -> e.getValue() :按键值对条件删除
注意:该方法是原子操作,执行期间其他线程若并发修改,行为由具体 Map 实现决定(如 HashMap 非线程安全,ConcurrentHashMap 则支持弱一致性)。
多线程场景优先选 ConcurrentHashMap
普通 HashMap 在多线程遍历 + 删除时极易出错。ConcurrentHashMap 提供了更宽松的安全保障:
- 它的
keySet()、values()、entrySet()返回的集合允许在迭代过程中调用remove() - 虽不保证看到“最新”修改(弱一致性),但不会抛异常
- 更稳妥的做法仍是搭配
iterator.remove()使用,而非依赖 for-each 中的remove()
避免这些错误写法
以下全部会导致 ConcurrentModificationException:
- 增强 for 循环中调用
map.remove(key) - 遍历
keySet()时用map.remove()删除 - 用
Stream.filter().collect()后赋值给原变量——这不是“边遍历边删”,而是新建 Map,原引用已变;若其他地方还持有旧引用,会造成数据不一致
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











