java中遍历map时应通过entryset().iterator()获取迭代器并调用it.remove()安全删除元素,避免concurrentmodificationexception;也可用java 8+的removeif方法简化操作。

Java 中在 Map 遍历时不能直接用 map.remove(key) 删除元素,否则会抛出 ConcurrentModificationException。正确方式是使用 Iterator 的 remove() 方法——但注意:Map 本身不支持直接获取 entry 迭代器(除非是 HashMap 等实现了 entrySet() 的子类),所以实际操作需通过 entrySet().iterator() 获取迭代器。
用 entrySet().iterator() 安全删除
这是最常用、最推荐的方式,适用于所有标准 Map 实现(HashMap、LinkedHashMap、TreeMap 等):
- 调用
map.entrySet().iterator()得到Iterator<map.entry>></map.entry> - 在循环中用
it.hasNext()和it.next()遍历 - 满足删除条件时,调用
it.remove()——该方法会安全移除当前 entry,不会破坏迭代器结构
示例:
Map<string integer> map = new HashMap();
map.put("a", 1);
map.put("b", null);
map.put("c", 3);
map.put("d", 0);
Iterator<map.entry integer>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<string integer> entry = it.next();
// 删除 value 为 null 或 0 的条目
if (entry.getValue() == null || entry.getValue() == 0) {
it.remove(); // ✅ 安全删除
}
}
// 此时 map 只剩 {"a"=1, "c"=3}
</string></map.entry></string>
避免常见错误写法
以下写法都会导致异常或逻辑错误:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
for (Map.Entry<k> e : map.entrySet()) { map.remove(e.getKey()); }</k>→ 抛ConcurrentModificationException -
Iterator<k> keyIt = map.keySet().iterator(); ... keyIt.remove();</k>→keySet().iterator().remove()是非法的,会抛UnsupportedOperationException(因为 keySet 迭代器不支持 remove) -
Iterator<v> valIt = map.values().iterator(); ... valIt.remove();</v>→ 同样不支持 remove(values() 返回的 Collection 通常不可修改)
替代方案:removeIf(Java 8+)
如果只是按 value 或 key 条件过滤,可直接用 entrySet().removeIf(...),更简洁且内部已封装了安全迭代逻辑:
map.entrySet().removeIf(entry -> entry.getValue() == null || entry.getValue() == 0);
本质等价于显式 iterator 写法,但更函数式、不易出错。
注意:ConcurrentHashMap 要另处理
如果是 ConcurrentHashMap,它允许并发修改,但 iterator 是弱一致性(weakly consistent),不抛 ConcurrentModificationException;不过其 iterator().remove() 仍可用,行为与普通 Map 一致。若需强一致性,建议改用 computeIfPresent / remove 等原子方法配合遍历判断。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










