entrySet() 返回 Set,比 keySet()+get() 快因避免重复哈希查找;遍历时 setValue() 在 HashMap 中安全但 TreeMap 不支持;Stream 操作更简洁高效;删除须用 Iterator.remove() 或 removeIf()。

entrySet() 返回的是什么类型,为什么比 keySet() + get() 快
entrySet() 返回的是 Set<map.entry>></map.entry>,每个元素是封装了键和值的 Map.Entry 对象。它避免了在遍历时反复调用 get() 查找值——而 keySet() 配合 map.get(key) 每次都要走哈希计算+桶查找,尤其在大 Map 或自定义 key 的场景下开销明显。
常见错误是写成这样:
for (String key : map.keySet()) {
String value = map.get(key); // 多余的哈希查找
}
正确做法直接解构 Map.Entry:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
}
增强 for 循环里修改 value 是否安全
对 Map.Entry 调用 setValue() 是允许的,且会同步更新原 Map 中对应键的值(前提是 Map 实现支持,如 HashMap、LinkedHashMap)。
但要注意以下几点:
-
TreeMap的entrySet()迭代器不支持setValue(),会抛UnsupportedOperationException - 不能通过
entry.setValue()修改 key 的内容(比如改String内容),否则破坏哈希一致性,后续get()可能失效 - 遍历中调用
map.remove(key)或iterator.remove()是安全的;但直接调用map.put()可能触发 fail-fast
Stream API 中用 entrySet() 做过滤或转换更简洁
相比先取 key 再 get(),用 entrySet().stream() 直接操作键值对语义更清晰、性能更好。
例如筛选 value > 10 的条目并转成新 Map:
Map<String, Integer> filtered = map.entrySet().stream()
.filter(entry -> entry.getValue() > 10)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
));
注意点:
- 如果 value 可能为 null,
entry.getValue() > 10会 NPE,需先判空 -
Collectors.toMap()在 key 冲突时默认抛IllegalStateException,必要时传第三个合并函数 - 对超大 Map,考虑用
parallelStream(),但要注意线程安全和装箱开销
迭代过程中删除元素必须用 Iterator.remove()
直接在增强 for 中调用 map.remove(key) 会导致 ConcurrentModificationException,因为 entrySet() 迭代器检测到结构修改。
安全删除方式只有两种:
- 用显式
Iterator并调用其remove()方法 - 用
removeIf()(JDK 8+),它内部封装了安全删除逻辑
示例:
Iterator<Map.Entry<String, Integer>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, Integer> entry = iter.next();
if (entry.getValue() < 0) {
iter.remove(); // ✅ 安全
}
}
或者更简洁:
map.entrySet().removeIf(entry -> entry.getValue() < 0);
别小看这个细节:线上高频遍历删元素的代码,漏掉这一步就容易崩。

















