迭代时如何删除和添加元素到TreeMap?

时间:2013-05-19 16:46:49

标签: java treemap

我想写这样的代码 -

for (Map.Entry<Long, Integer> e : map.entrySet()){
    map.remove(k);
    map.put(x, value);
}

但我得到java.util.ConcurrentModificationException 我也尝试使用Iterator,但我得到了相同的Exception

5 个答案:

答案 0 :(得分:9)

解释导致ConcurrentModificationException

的原因
map.remove(k);
map.put(x, value);

for-each循环还在内部创建entrySet map的迭代器。在迭代地图时,您已经通过将值再次放到导致此map.put(x,value)的地图(ConcurrentModificationException)来修改地图的结构。

documentation -

中解释得很清楚
  

此类的所有“集合视图”返回的迭代器   方法“是快速失败的:如果地图在结构上被修改了   创建迭代器之后的时间,除了通过之外的任何方式   迭代器自己的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。 现在谈谈如何迭代新添加的元素。

  1. 创建HashMap的副本。因此,您将迭代一个并修改另一个Map
  2. 由于要求在Map中添加和删除元素,我想使用ListIterator [这与普通Iterator]不同。
  3. 我将获得Map1的keyset并使用ArrayList(Collection<? extends E> c)将其转换为列表。
  4. 现在我将从步骤3中创建的ListIterator获取List,然后添加,删除ListIterator以及Map2中的元素[记住您需要添加,删除{} {1}}和Map2]。

答案 4 :(得分:0)

因为你做不到。

一个简单的解决方案是使用另一个临时地图放置你想要的值,最后用原始地图切换指针(即Map = newMap)