我想写这样的代码 -
for (Map.Entry<Long, Integer> e : map.entrySet()){
map.remove(k);
map.put(x, value);
}
但我得到java.util.ConcurrentModificationException
我也尝试使用Iterator
,但我得到了相同的Exception
答案 0 :(得分:9)
解释导致ConcurrentModificationException
map.remove(k);
map.put(x, value);
for-each循环还在内部创建entrySet
map
的迭代器。在迭代地图时,您已经通过将值再次放到导致此map.put(x,value)
的地图(ConcurrentModificationException
)来修改地图的结构。
此类的所有“集合视图”返回的迭代器 方法“是快速失败的:如果地图在结构上被修改了 创建迭代器之后的时间,除了通过之外的任何方式 迭代器自己的remove方法,迭代器会抛出一个 ConcurrentModificationException的。因此,面对并发 修改,迭代器快速而干净地失败,而不是 在不确定的时间冒着任意的,非确定性的行为 在将来。
如何解决此问题 -
您必须在迭代时更改此地图的结构,您可以稍后插入此值,例如保留临时地图,并在迭代完成其工作后将其添加到主地图。
Map<Long, Integer> tempMap = new HashMap<>();
for (Map.Entry<Long, Integer> e : map.entrySet()){
map.remove(k);
tempMap.put(x, value);
}
map.putAll(tempMap);
答案 1 :(得分:2)
迭代副本,你可以添加/删除就好了:
for (Map.Entry<Long, Integer> e : new LinkedHashMap<Long, Integer>(map).entrySet()){
map.remove(k);
map.put(x, value);
}
它甚至不再是代码行,因为复制ims是通过复制构造函数在线进行的。选择LinkedHashMap
来保留迭代顺序(如果重要的话)。
答案 2 :(得分:2)
下面给出了用于从地图中删除元素的示例代码段。
for(Iterator<Map.Entry<Long, Integer>> it = map.entrySet().iterator();it.next();)
{
Map.Entry<String, String> entry = it.next();
if(//some logic)
it.remove();
}
如果您的代码涉及大量添加和删除,您可能只想使用ConcurrentHashMap。ConcurrentHashMap
答案 3 :(得分:1)
您必须使用复制构造函数创建地图的副本。现在迭代1并修改第二个地图。 我假设您不需要迭代新增加的值,因为它没有多大意义。
您可以通过创建副本来完成任务,因为密钥在两者中都保持相同。
编辑:
我不认为将新添加的元素迭代到Hashmap是一个好主意。如果你检查Iterator提供的API,你会发现只有删除方法,其中没有添加方法。这有一个原因,你可以检查javadoc。 现在谈谈如何迭代新添加的元素。
HashMap
的副本。因此,您将迭代一个并修改另一个Map
。Map
中添加和删除元素,我想使用ListIterator
[这与普通Iterator
]不同。keyset
并使用ArrayList(Collection<? extends E> c)
将其转换为列表。ListIterator
获取List
,然后添加,删除ListIterator
以及Map2中的元素[记住您需要添加,删除{} {1}}和Map2]。 答案 4 :(得分:0)
因为你做不到。
一个简单的解决方案是使用另一个临时地图放置你想要的值,最后用原始地图切换指针(即Map = newMap)