在 java 中,通过 iterator 删除 hashmap 元素必须使用迭代器自身的 remove() 方法。直接调用 hashmap 的 remove() 或在增强 for 循环中操作会导致 concurrentmodificationexception。具体做法是获取 entryset 的迭代器,遍历过程中判断条件满足时调用 iterator.remove(),这样能安全地从底层数组和链表/红黑树中移除节点并更新计数。

为什么不能用增强 for 循环删除
增强 for 循环底层依赖 Iterator,但它在每次迭代开始时检查 modCount。如果在循环体内修改了 Map 结构(如调用 map.remove(key)),modCount 会改变,下一次迭代时迭代器检测到不一致就会抛出异常。因此,任何非迭代器方式的删除都是非法的。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class SafeRemoveDemo {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
// 错误示范:这会抛出 ConcurrentModificationException
// for (Map.Entry<String, Integer> entry : map.entrySet()) {
// if (entry.getKey().equals("A")) {
// map.remove("A"); // 非法操作
// }
// }
// 正确做法:使用 Iterator
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
if (entry.getKey().equals("A")) {
iterator.remove(); // 安全删除
}
}
System.out.println(map); // 输出: {B=2, C=3}
}
}上述代码展示了正确的删除流程。首先获取 entrySet() 的迭代器,然后使用 while 循环配合 hasNext() 和 next()。当找到目标键 "A" 时,调用 iterator.remove()。该方法内部会同步更新 modCount,避免后续迭代检测失败。最终 Map 中只保留 "B" 和 "C"。
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
立即学习“Java免费学习笔记(深入)”;
Iterator remove() 的内部机制
iterator.remove() 并非简单地将值设为 null,而是真正从 HashMap 的内部数据结构中移除节点。它调用 HashMap.this.removeEntryForKey(key),涉及哈希表的重排、链表节点的 unlink 或红黑树的 rebalance。这个过程比直接赋值开销大,但保证了数据一致性。此外,remove() 只能调用一次,连续调用会抛出 IllegalStateException,因为上次删除后迭代器状态已重置。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class RemoveValidation {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("key1", "val1");
map.put("key2", "val2");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
if (entry.getKey().equals("key1")) {
it.remove();
// 如果再次调用 it.remove(),将抛出 IllegalStateException
// it.remove();
}
}
System.out.println(map.size()); // 输出: 1
}
}验证代码显示,remove() 调用后 Map 大小减一。若尝试连续调用,程序会崩溃。这强调了在一次 next() 之后仅允许一次 remove() 的规则。开发者应确保逻辑中不会意外重复调用,否则需重新获取迭代器。

















