9

我想写这样的代码 -

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

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

4

6 回答 6

11

解释为什么会导致ConcurrentModificationException

map.remove(k);
map.put(x, value);

for-each 循环还在内部创建 of 的迭代entrySetmap。在遍历 map 时,您通过将值再次放入 map( map.put(x,value)) 修改了 map 的结构,这导致了这种情况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);
于 2013-05-19T17:10:18.817 回答
4

迭代一个副本,你可以添加/删除就好了:

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

它甚至不再是代码行,因为复制 ims 是通过复制构造函数内联生成的。LinkedHashMap选择保留迭代顺序(如果重要的话)。

于 2013-05-20T04:39:05.083 回答
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。并发哈希映射

于 2014-09-15T18:12:23.563 回答
1

You will have to create a copy of your map using copy constructor. Now iterate on 1 and modify second map. I am assuming that you will not need to iterate newly added value as it wont make much sense.

You can achieve your task by creating a copy is because the keys will remain same in both.

EDIT:

I dont think its a good idea to iterate the newly added element to a Hashmap. If you check the api's provided by Iterator then you will find only remove method, there is no add method in it. There is a reason behind this and you can check javadoc for this. Now coming to the point, on how to iterate newly added element.

  1. Create a copy of your HashMap. So you will iterate one and modify the the other Map.
  2. As the requirement is to both add and remove elements in Map, i would like to use ListIterator for this [this is different from normal Iterator].
  3. I will get the keyset of Map1 and convert it to a list using ArrayList(Collection<? extends E> c).
  4. Now i will get ListIterator from List created in step 3, and add, remove elements in ListIterator as well as in Map2 [Remeber you need to add , remove both in ListIterator and Map2].
于 2013-05-19T16:56:22.537 回答
0

因为你不能那样做。

一个简单的解决方案是使用另一个临时映射,在其中放置所需的值,最后用原始映射切换指针(即 Map = newMap )

于 2013-05-19T17:03:29.277 回答
0

尝试按如下方式浏览地图

while (tree_map.size() > 0){
     // if k is key
     if (tree_map.containsKey()){
        tree_map.remove(k);
     }
     tree_map.put(x, value);
     break;
     // can go through the for loop or other code as per requirements
 }
于 2022-01-30T10:36:45.437 回答