Java Map 的 entrySet() 方法详解及用法,一篇就够了!
引言
在 Java 集合框架中,Map 接口的 entrySet() 方法是最常用且最高效的遍历方式之一。它返回 Map 中所有键值对映射关系的集合视图(Set<Map.Entry<K, V>>),通过这个视图我们可以同时访问 key 和 value,甚至在遍历过程中修改 Map 的内容。
相比 keySet()(只能取 key 再 get value)和 values()(只能取 value),entrySet() 在需要同时操作键和值时性能更好,因为避免了重复的 key 查找操作。
掌握 entrySet(),能让你写出更优雅、更高效的 Map 遍历代码!
entrySet() 方法签名与返回值
public Set<Map.Entry<K, V>> entrySet()
- 返回值:一个包含 Map 中所有映射关系的
Set视图。 - 每个元素是
Map.Entry<K, V>类型对象,代表一个键值对。 - 该 Set 是 Map 的后台视图(backing view):对 Set 的修改会反映到原 Map,反之亦然。
- 不支持添加新元素(会抛 UnsupportedOperationException),但支持 remove 和 clear。
Map.Entry 接口核心方法
interface Map.Entry<K, V> {
K getKey(); // 获取键
V getValue(); // 获取值
V setValue(V value); // 修改值(会同步修改原 Map)
boolean equals(Object o);
int hashCode();
}
重点:setValue() 可以直接修改 Map 中的值!
常见用法详解
用法1:增强 for 循环遍历(最常用)
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 10);
map.put("Banana", 20);
map.put("Orange", 15);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " = " + value);
}
输出:
Apple = 10
Banana = 20
Orange = 15
优势:代码清晰,性能最佳(推荐!)
用法2:Iterator 显式迭代器(可安全删除元素)
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
if (entry.getValue() < 18) {
iterator.remove(); // 安全删除
}
}
关键:删除时必须用 iterator.remove(),不能用 map.remove(key)(会抛 ConcurrentModificationException)。
用法3:在遍历中修改值
for (Map.Entry<String, Integer> entry : map.entrySet()) {
// 将所有值翻倍
entry.setValue(entry.getValue() * 2);
}
System.out.println(map); // {Apple=20, Banana=40, Orange=30}
这是 entrySet() 的独有能力!用 keySet() 做不到这么简洁。
用法4:结合 Java 8 Lambda 表达式(现代写法)
// 遍历打印
map.entrySet().forEach(entry ->
System.out.println(entry.getKey() + " -> " + entry.getValue())
);
// 修改值
map.entrySet().forEach(entry -> entry.setValue(entry.getValue() + 100));
// 过滤并收集新 Map
Map<String, Integer> filtered = map.entrySet().stream()
.filter(entry -> entry.getValue() > 15)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
));
用法5:排序 Map(经典应用)
List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
list.sort(Map.Entry.comparingByValue(Comparator.reverseOrder())); // 按值降序
// 前3名
for (int i = 0; i < Math.min(3, list.size()); i++) {
System.out.println(list.get(i).getKey() + ": " + list.get(i).getValue());
}
三种遍历方式性能对比
| 方式 | 代码复杂度 | 性能(大 Map 时) | 可修改值 | 可安全删除 |
|---|---|---|---|---|
| entrySet() | 低 | 最快 | 是 | 是 |
| keySet() + get(key) | 中 | 慢(重复查找) | 是 | 是(慎用) |
| values() | 高 | 快 | 否 | 否 |
结论:能用 entrySet() 就优先用!
注意事项与常见坑
entrySet()返回的是视图,不是副本。修改视图 = 修改原 Map。- 某些 Map 实现(如 ConcurrentHashMap)在迭代时若结构发生变化仍可能抛异常,建议使用 Iterator。
- 不支持向 entrySet 添加新元素:
map.entrySet().add(new AbstractMap.SimpleEntry<>("new", 1)); // 抛 UnsupportedOperationException
- 在多线程环境下,建议使用 ConcurrentHashMap 或外部同步。
总结:什么时候用 entrySet()
- 需要同时访问 key 和 value → 首选 entrySet()
- 需要在遍历中修改值 → 必须用 entrySet()
- 需要删除元素 → 用 entrySet() + Iterator
- 需要排序或流式处理 → entrySet() 是最佳起点
掌握了 entrySet(),你就掌握了 Java Map 遍历的精髓!下次处理 Map 时,优先写:
for (Map.Entry<K, V> entry : map.entrySet()) { ... }
代码更简洁,性能更优秀!建议收藏本文,反复实践这几种用法,轻松进阶 Java 集合高手!