entrySet()遍历最常用且高效,直接获取键值对避免重复查表,性能优于keySet()和forEach();唯一安全删除方式是Iterator.remove()。
直接遍历 entrySet() 是 Java 中遍历 HashMap 的首选方式,它返回的是 Set,每个元素都包含键和值,避免了重复查表开销。
keySet() 再逐个 get() 快一倍左右(尤其在大 Map 时)ConcurrentModificationException)Mapmap = new HashMap<>(); map.put("a", 1); map.put("b", 2); for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key + " -> " + value); }
如果逻辑只需要键,或者后续还要用这个键做其他操作(比如查另一个 Map),keySet() 更轻量。但它每次取值都要走一次哈希查找,性能不如 entrySet()。
null,get(null) 返回 null,但无法区分是没找到还是值本身就是 null
entrySet() 一致,同样不支持边遍历边 remove()(除非用 Iterator.remove())for (String key : map.keySet()) {
Integer value = map.get(key); // 多一次 hash 查找
if (value != null && value > 0) {
System.out.println(key);
}
}
Java 8 引入的 forEach() 看起来简洁,但底层仍基于 entrySet().iterator(),语义上等价于增强 for 循环,**不是并行操作**。
BiConsumer super K, ? super V>,第一个是 key,第二个是 value
null,Lambda 体内要主动判空,否则可能触发 NullPointerException
map.put() 或 map.remove() 会立即抛出 ConcurrentModificationException
map.forEach((key, value) -> {
if (value != null) {
System.out.println(key + "=" + value);
}
});
想在遍历过程中删掉某些键值对?别用 map.remove(key),必须用迭代器自己的 remove() 方法,否则一定报错。
entrySet().iterator() 和 keySet().iterator() 都提供 remove()
next() 后最多只能调用一次 remove(),重复调用抛 IllegalStateException
Iterator遍历本身不难,真正容易出问题的是混用不同遍历方式、在循环里误删元素、或忽略> iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); if (entry.getValue() == 1) { iter.remove(); // 安全删除 } }
null 值语义——这些地方一旦出错,往往表现为偶发的 NullPointerException 或 ConcurrentModificationException,调试起来反而比写逻辑花更长时间。