我在下面有以下代码
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
的例外。我已经研究过如何解决这个问题,但似乎没有对我有所帮助。
我在上面的代码上做的是随机删除一个条目。我怎样才能在那里实现它?
答案 0 :(得分: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的评论)
是的,通过Iterator#remove()
对HashMap.entrySet()返回的Set
进行的删除将反映在基础Map
中,因为Set
由其支持。在这里引用JavaDoc:
返回此映射中包含的映射的Set视图。该集由地图支持,因此对地图的更改将反映在集中,反之亦然。
答案 1 :(得分: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();
}
}
如何运作?
ConcurrentModificationException
的javadoc说:
如果单个线程发出违反对象合同的一系列方法调用,则该对象可能会抛出此异常。例如,如果线程在使用失败快速迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。
字段int expectedModCount
被启动为等于字段protected transient int modCount = 0;
(这对于集合和地图有效),modCount
会跟踪对象的结构修改。如果迭代某点的modCount
不等于expectedModCount
,则会抛出ConcurrentModificationException
。
使用Iterator
对地图/集合进行结构更改(如删除元素),我们确保删除操作将正确执行,例如modCount
将等于expectedModCount
。
答案 2 :(得分:0)
在forEach循环中使用iterator并使用iterator.remove();
答案 3 :(得分:0)
是you can't delete entries in a Map while traversing it by it's own property
。不同的方法。