迭代Map 时出现ConcurrentModificationException

我在下面有以下代码

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

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

除非使用Iterator ,否则在迭代时无法从集合中删除元素。

这就是引起exception的原因。

 buyingItemEnumerationMap.remove(item.getKey()); 

使用Iterator #remove()删除元素,同时迭代你的集合

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

编辑 :(回应OP的评论)
是的,通过Iterator#remove() #remove()对HashMap.entrySet()返回的Set Iterator#remove()将反映在底层Map因为Set支持它。 在这里引用JavaDoc:

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

使用Iterator

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

这个怎么运作 ?

ConcurrentModificationException的javadoc说:

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

字段int expectedModCount被启动为等于字段protected transient int modCount = 0; (这对于集合和地图有效), modCount会跟踪对象的结构修改。 如果迭代某点的modCount不等于expectedModCount ,则抛出ConcurrentModificationException

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

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

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