3

我在下面有以下代码

Map<String, Integer> buyingItemEnumerationMap = this.toBuyItemEnumeration;
for (Entry<String, Integer> item : buyingItemEnumerationMap.entrySet()) {
   if(RandomEngine.boolChance(50)){ //will delete?
    buyingItemEnumerationMap.remove(item.getKey());
   }
   if(buyingItemEnumerationMap.size() == 1){
    break;
   }
}

现在我正在使用一个 android 游戏,上面的代码以多线程方式运行。现在我有一个例外,即java.util.ConcurrentModificationException. 我已经研究过如何解决这个问题,但似乎对我不起作用。我在上面的代码上做的是随机删除一个条目。我怎样才能在那里实现它?

4

4 回答 4

9

除非您使用Iterator.

这就是导致异常的原因。

buyingItemEnumerationMap.remove(item.getKey());

使用Iterator#remove()在迭代您的集合时删除一个元素,例如

Iterator<Map.Entry<String, Integer>> iterator = 
                           buyingItemEnumerationMap.entrySet().iterator();
while (iterator.hasNext()) {
   Map.Entry<String, Integer> item = iterator.next();
   if(RandomEngine.boolChance(50)){ //will delete?
      iterator.remove();
   }
   //..
}

编辑:(响应 OP 的评论)
是的,通过 HashMap.entrySet() 返回的删除Iterator#remove()反映Set在底层,因为它得到了它的支持。在这里引用 JavaDoc:MapSet

返回此映射中包含的映射的 Set 视图。该集合由映射支持,因此对映射的更改会反映在集合中,反之亦然

于 2013-07-17T07:26:13.963 回答
6

使用Iterator.

Iterator<Map.Entry<String, Integer>> iter = this.toBuyItemEnumeration;
while (iter.hasNext()) {
    Map.Entry<String, Integer> entry = iter.next();
    if (some-condition){
        iter.remove();
    }
}

这个怎么运作 ?

javadocConcurrentModificationException说:

如果单个线程发出一系列违反对象约定的方法调用,则该对象可能会抛出此异常。例如,如果线程在使用快速失败迭代器迭代集合时直接修改了集合,则迭代器将抛出此异常。

该字段int expectedModCount被初始化为等于该字段protected transient int modCount = 0;(这对集合和映射有效),并modCount跟踪对象的结构修改。如果modCount在迭代的某个点不等于expectedModCount,则ConcurrentModificationException抛出 a。

通过使用Iterator对地图/集合进行结构更改(如删除元素),我们确保删除操作将被正确执行,例如modCount将等于expectedModCount.

于 2013-07-17T07:26:44.090 回答
0

在 forEach 循环中使用迭代器并使用 iterator.remove();

于 2013-07-17T07:26:54.453 回答
0

you can't delete entries in a Map while traversing it by it's own property的。不同的方法。

于 2013-07-17T07:29:13.270 回答