因为map未实现iterable接口,无法直接用for-each遍历;必须通过entryset()、keyset()或values()获取可迭代视图,其中entryset()最安全高效,可同时获取键值引用且避免重复查找。

为什么不能直接用 for (String key : map) 遍历 Map
因为 Map 不是 Iterable,它没有实现 Iterator 接口,所以不能直接用于增强 for 循环。常见错误是写成 for (String key : map),编译器会报错:Cannot iterate over a Map。必须先调用 entrySet()、keySet() 或 values() 获取可迭代视图。
for-each 遍历 entrySet() 的标准写法
最安全、最通用的方式是遍历 entrySet(),每个元素是 Map.Entry<k></k> 类型,可通过 getKey() 和 getValue() 同时拿到键与值的引用(不是拷贝)。
示例(Java 8+):
Map<string integer> map = new HashMap();
map.put("a", 1);
map.put("b", 2);
for (Map.Entry<string integer> entry : map.entrySet()) {
String key = entry.getKey(); // 引用原 key 对象
Integer value = entry.getValue(); // 引用原 value 对象
System.out.println(key + " -> " + value);
}</string></string>
- 必须声明泛型类型(如
Map.Entry<string integer></string>),否则getKey()返回Object,需强制转型 -
entrySet()返回的是底层数据结构的“视图”,不复制键值对,修改 entry 的 value(若支持)会反映到原 map 中(如entry.setValue(99)对HashMap有效) - 但不能通过 entry 修改 key;也不能调用
remove()等结构性修改方法,除非用Iterator.remove()
遍历时修改 value 的注意事项
想在循环中更新某个 value,推荐用 entry.setValue(),而不是 map.put(key, newValue) —— 后者可能触发哈希重计算或冗余查找,且在并发 map(如 ConcurrentHashMap)中更易出错。
-
entry.setValue()是原子操作(对大多数标准实现),且保持 entry 引用有效性 - 但
TreeMap不支持setValue()(抛UnsupportedOperationException),因其 value 变更可能破坏排序逻辑 - 如果 map 是不可变的(如
Collections.unmodifiableMap()),调用setValue()也会失败
性能与兼容性差异:entrySet() vs keySet() + get()
虽然也能写成 for (String key : map.keySet()) { Integer v = map.get(key); },但这是低效的:
- 每次
get()都要重新哈希、寻址,时间复杂度 O(1) 但常数较大;而entrySet()遍历是单次线性扫描,实际更快 - 对
LinkedHashMap,entrySet()保持插入/访问顺序;keySet()视图也保持,但多一次哈希查找 - 对
TreeMap,两者都按 key 排序,但entrySet()仍少一次get()调用开销
真正容易被忽略的是:某些自定义 Map 实现(比如包装类)可能让 entrySet() 返回的 Entry 不支持 setValue(),甚至返回的 Entry 是只读快照 —— 此时必须看文档或源码确认行为。










