entrySet()返回Set<Map.Entry<K,V>>类型,内部存储键值对对象;遍历时须声明Map.Entry变量,不可用索引访问,推荐增强for循环解构getKey()/getValue()。

entrySet 返回的是什么类型
entrySet() 方法返回的是 Set<map.entry v>></map.entry>,不是 List,也不是键或值的单独集合。它内部存储的是实现了 Map.Entry 接口的对象,每个对象同时持有当前键和值的引用。直接用 for-each 遍历时,变量类型必须声明为 Map.Entry<k v></k>,否则编译报错。
常见错误现象:for (String s : map.entrySet()) 会提示类型不匹配;map.entrySet().get(0) 编译失败——因为 Set 没有 get(int) 方法。
怎么安全高效地遍历并取出 key 和 value
最常用且推荐的方式是增强 for 循环配合 Map.Entry 解构:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
// 处理逻辑
}
注意点:
- 不要在循环中调用
entry.setValue(...)修改值后又继续使用该 entry(某些 Map 实现如TreeMap可能抛ConcurrentModificationException,但HashMap允许) - 如果只需要 key 或 value,不如直接用
keySet()或values(),避免构造多余的Entry对象,节省内存 - Java 8+ 可用
forEach+ Lambda,但无法在 lambda 中break或continue,控制力较弱
为什么不能用普通 for 循环加索引
entrySet() 返回的是 Set,而 Set 不保证顺序(除非是 LinkedHashSet 背后的实现,如 LinkedHashMap),更没有随机访问能力。所以以下写法非法:
for (int i = 0; i < map.entrySet().size(); i++) {
// ❌ 编译失败:Set 没有 get(i)
Map.Entry e = map.entrySet().get(i);
}
如果你依赖插入顺序,应确认底层 Map 是 LinkedHashMap,但仍须通过迭代器或 for-each 访问,不能靠下标。
性能与兼容性差异
entrySet() 遍历比分别遍历 keySet() 再查 get(key) 更快,尤其对大 Map:
- 前者是一次哈希定位 + 单次遍历;后者每次
get()都要重新计算 hash、寻址、可能还要处理碰撞 - 在
ConcurrentHashMap中,entrySet()返回的是弱一致视图,遍历时可能看不到最新 put 的条目,但不会抛异常 -
ImmutableMap(如 Guava)也支持entrySet(),但返回的 Set 是不可变的,任何修改操作都会抛UnsupportedOperationException
真正容易被忽略的是:遍历时若对原 Map 做结构性修改(如 put、remove),除了 ConcurrentHashMap,其他大多数实现都会导致 ConcurrentModificationException——哪怕你只是在遍历 entrySet()。

















