仅修改HashMap的值是否会触发Concurrent Modification Exception?
关于HashMap遍历中修改值是否触发ConcurrentModificationException的问题
先给你明确结论:你代码里的操作不会触发ConcurrentModificationException,这也是你测试过程中没遇到异常的核心原因。
为什么不会触发?
HashMap的快速失败迭代器(比如keySet()返回的迭代器)抛出CME的核心判定条件是:迭代器创建后,Map的结构被修改了——这里的「结构修改」特指以下几种操作:
- 向Map中添加新的键值对
- 从Map中删除已有键值对
- 修改Map的容量(比如触发扩容导致rehash)
而你代码里的variableMap.put(innerVariable, ...)是对已有键对应的值进行更新,这个操作不会改变Map的结构(键的数量没有变化,也不会触发扩容逻辑),所以迭代器不会检测到结构变更,自然不会抛出异常。
结合你的代码具体分析
看你的代码片段:
for(String variable:variableMap.descendingKeySet()) { for (String innerVariable : variableMap.keySet()) { variableMap.put(innerVariable, variableMap.get(innerVariable).replace("$" + variable, variableMap.get(variable))); } }
内层循环里的put操作都是针对keySet()中已存在的键,只是更新它们关联的值,完全没有添加新键、删除旧键的行为,所以无论外层还是内层的迭代器,都不会触发CME。
补充需要注意的触发场景
如果你的代码改成以下情况,就会大概率触发ConcurrentModificationException:
- 在遍历过程中调用
variableMap.remove(innerVariable)删除键 - 在遍历过程中调用
variableMap.put(newKey, newValue)添加新键 - 极端情况下,大量值更新间接触发Map扩容(不过这种情况非常少见,因为扩容逻辑是基于键的数量和负载因子,和值的大小无关)
内容的提问来源于stack exchange,提问作者Chirag
相关产品推荐
相关产品推荐

