迭代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。