迭代Map时出现ConcurrentModificationException

Mp *_*ega 3 java iteration concurrency android map

我在下面有以下代码

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;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

Rav*_*yal 9

除非使用,否则在迭代时不能从集合中删除元素Iterator.

这就是导致例外的原因.

buyingItemEnumerationMap.remove(item.getKey());
Run Code Online (Sandbox Code Playgroud)

使用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();
   }
   //..
}
Run Code Online (Sandbox Code Playgroud)

编辑:(响应OP的评论)
是的,删除通过完成Iterator#remove()Set由归国 HashMap.entrySet()在底层将反映MapSet是它的支持.在这里引用JavaDoc:

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


Kon*_*kov 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这个怎么运作 ?

javadoc ConcurrentModificationException说:

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

该字段int expectedModCount被启动为等于字段protected transient int modCount = 0;(这对于集合和映射有效),并modCount跟踪对象的结构修改.如果modCount在迭代的某个时刻变得不相等expectedModCount,则ConcurrentModificationException抛出a.

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