Map.Entry 的 setValue() 方法可在遍历中安全更新值,但仅适用于支持修改的 Map(如 HashMap),不适用于不可变 Map 或 ConcurrentHashMap;需避免在遍历时调用 map.put()/remove(),以防 ConcurrentModificationException。

在 Java 中,Map.Entry 的 setValue() 方法确实允许你在遍历过程中直接修改对应键的值,但必须注意:它只对支持修改的 Map 实现(如 HashMap、LinkedHashMap、TreeMap)有效,且不能用于不可变 Map(如 Collections.unmodifiableMap())或某些并发 Map(如 ConcurrentHashMap 的部分迭代场景)。
使用 entrySet() 遍历并安全调用 setValue()
推荐通过 map.entrySet().iterator() 或增强 for 循环遍历 Entry,然后调用 entry.setValue(newVal)。该操作等价于 map.put(entry.getKey(), newVal),但更高效(避免二次哈希查找)。
- ✅ 正确示例(HashMap):
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
<p>for (Map.Entry<String, Integer> entry : map.entrySet()) {
if ("b".equals(entry.getKey())) {
entry.setValue(200); // 直接更新 value
}
}
// 此时 map.get("b") == 200注意迭代器的并发修改限制
虽然 setValue() 是合法的结构性修改,但你不能在遍历时调用 map.remove() 或 map.put(),否则会触发 ConcurrentModificationException。而 entry.setValue() 是被明确允许的例外 —— 它不改变 Map 结构(键集合不变),仅更新值。
- ⚠️ 错误写法(抛异常):
for (Map.Entry<String, Integer> entry : map.entrySet()) {
map.put("newKey", 999); // ❌ 触发 ConcurrentModificationException
entry.setValue(100); // ✅ 允许
}在 forEach 和 Stream 中的限制
Map.forEach(BiConsumer) 接收的是 key 和 value 的副本,无法访问 Entry 对象,因此不能调用 setValue();同理,stream().forEach() 中拿到的也是 Map.Entry 的副本(取决于具体实现),但标准 JDK 实现中,entrySet().stream() 返回的 Entry 是可变的(对 HashMap 等成立),不过语义上不鼓励依赖此行为。
立即学习“Java免费学习笔记(深入)”;
- ✅ 安全替代方式(仍用 entrySet + 迭代器):
map.entrySet().forEach(entry -> {
if (entry.getValue() < 5) {
entry.setValue(entry.getValue() * 10);
}
});该写法在 JDK 8+ 中对 HashMap 等是安全的,因为 forEach 内部仍基于迭代器,且 setValue 是被支持的操作。
特殊 Map 的兼容性提醒
ConcurrentHashMap 的 entrySet() 迭代器返回的 Entry 不支持 setValue()(会抛 UnsupportedOperationException),因其内部 Entry 是不可变快照。如需更新,应使用 compute()、replace() 或 merge() 等原子方法。
- ✅ ConcurrentHashMap 安全更新方式:
concurrentMap.compute("key", (k, oldVal) -> oldVal == null ? 0 : oldVal * 2);


















