在Java里Map遍历有哪些方式_Java键值遍历方法说明

最推荐 Map 遍历方式是 entrySet() + 增强 for 或 forEach(),性能优、代码简洁、支持安全删除和值修改;keySet() + get() 因重复哈希查找而低效,仅适用于纯 key 场景或小数据量。

Map 遍历最常用、最推荐的方式是 entrySet() + 增强 for 循环或 forEach(),性能好、代码干净、支持安全修改;而仅用 keySet() + get() 的方式,看似简单,实际在大数据量下会多一次哈希查找,属于典型“看着对、跑得慢”的写法。

entrySet() 是默认首选:一次拿到 key 和 value

这是 Java 中遍历 Map 最高效也最通用的方式。它直接返回 Set>,每个 Map.Entry 对象天然封装了键和值,无需二次查表。

  • 避免重复哈希计算:相比 keySet() 方式,

    节省约 50% 的寻址开销
  • 支持遍历时安全删除:调用 entry.remove() 不会抛 ConcurrentModificationException
  • 支持直接修改值:entry.setValue(newVal)map.put(key, newVal) 更轻量
Map map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);

for (Map.Entry entry : map.entrySet()) {
    System.out.println(entry.getKey() + " → " + entry.getValue());
}

forEach() + Lambda:JDK 8+ 的简洁写法

Map.forEach() 底层就是基于 entrySet() 实现的,语法更紧凑,适合只读遍历场景。

  • 要求 JDK ≥ 8,不兼容老版本(如 Android API 23 及以下需注意)
  • 不能在 lambda 里 break/continue,也不支持 throw 受检异常
  • 若需过滤或转换,应改用 stream(),而非硬塞逻辑进 forEach
map.forEach((key, value) -> {
    if (value > 1) {
        System.out.println(key + " is large");
    }
});

keySet() 遍历:只适合“真只需要 key”或小数据量

map.keySet() 再逐个 map.get(key) 是新手常见写法,但它是性能陷阱——每次 get() 都要重新计算哈希、定位桶、处理冲突链。

  • 当 Map 是 ConcurrentHashMap 时,get() 还可能触发额外的 volatile 读
  • 无法在遍历中安全删除元素(iterator.remove() 可以,但 map.remove(key) 会报错)
  • 如果业务只要 key(比如做权限校验、日志打点),那它反而更清晰
for (String key : map.keySet()) {
    // ✅ 合理:只关心 key
    log.info("Processing key: {}", key);

    // ❌ 低效:又去 get 一次 value
    Integer val = map.get(key); // 多一次哈希查找!
}

values() 和 stream():用前先想清楚代价

map.values() 只返回 Collection,完全丢弃 key —— 如果后续还要反查 key,就掉坑里了;stream() 看似现代,但 map.entrySet().stream() 会额外创建 Stream 对象和中间操作节点,纯遍历毫无优势。

  • values() 适合统计、聚合等只依赖 value 的场景(如求最大值、平均分)
  • stream() 仅在需要 filter/map/collect 等链式操作时才值得用,否则就是杀鸡用牛刀
  • 所有 Stream 操作默认是串行的,没加 parallelStream() 就别幻想并发加速
别迷信“写法新=更好”。真正影响性能的是哈希查找次数和内存访问局部性,不是括号多几个。哪怕你用 forEach(),如果里面嵌套了 map.get(),照样退化成 keySet() 级别的低效。