在Java里如何遍历HashMap集合_Java键值对迭代说明

entrySet()遍历最常用且高效,直接获取键值对避免重复查表,性能优于keySet()和forEach();唯一安全删除方式是Iterator.remove()。

用 entrySet() 遍历最常用也最高效

直接遍历 entrySet() 是 Java 中遍历 HashMap 的首选方式,它返回的是 Set>,每个元素都包含键和值,避免了重复查表开销。

  • 比分别调用 keySet() 再逐个 get() 快一倍左右(尤其在大 Map 时)
  • 支持在循环中安全修改值(但不能删 key,否则抛 ConcurrentModificationException
  • 泛型清晰,编译期就能检查类型
Map map = 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);
}

遍历 keySet() 适合只关心键或需复用 key 的场景

如果逻辑只需要键,或者后续还要用这个键做其他操作(比如查另一个 Map),keySet() 更轻量。但它每次取值都要走一次哈希查找,性能不如 entrySet()

  • 适用于「先过滤键,再处理对应值」的流程
  • 注意:若键为 nullget(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);
    }
}

用 forEach() + Lambda 要小心空指针和并发修改

Java 8 引入的 forEach() 看起来简洁,但底层仍基于 entrySet().iterator(),语义上等价于增强 for 循环,**不是并行操作**。

  • 参数是 BiConsumer super K, ? super V>,第一个是 key,第二个是 value
  • 如果 value 可能为 null,Lambda 体内要主动判空,否则可能触发 NullPointerException
  • 在遍历过程中调用 map.put()map.remove() 会立即抛出 ConcurrentModificationException
map.forEach((key, value) -> {
    if (value 

!= null) { System.out.println(key + "=" + value); } });

Iterator.remove() 是唯一安全的遍历中删除方式

想在遍历过程中删掉某些键值对?别用 map.remove(key),必须用迭代器自己的 remove() 方法,否则一定报错。

  • entrySet().iterator()keySet().iterator() 都提供 remove()
  • 每调用一次 next() 后最多只能调用一次 remove(),重复调用抛 IllegalStateException
  • 删除后当前 entry 不再有效,但不影响后续迭代
Iterator> iter = map.entrySet().iterator();
while (iter.hasNext()) {
    Map.Entry entry = iter.next();
    if (entry.getValue() == 1) {
        iter.remove(); // 安全删除
    }
}
遍历本身不难,真正容易出问题的是混用不同遍历方式、在循环里误删元素、或忽略 null 值语义——这些地方一旦出错,往往表现为偶发的 NullPointerExceptionConcurrentModificationException,调试起来反而比写逻辑花更长时间。