为什么ArrayList中的ConcurrentModificationException?

时间:2012-10-09 05:13:58

标签: java collections

为什么下面的代码抛出ConcurrentModificationException? Josh Bloch可以避免ConcurrentModificationException。

ArrayList<Integer> list=new ArrayList<Integer>();
list.add(100);
list.add(200);
list.add(300);
list.add(400);
for(Integer field : list) {    
    list.remove(field);
    list.add(200);
}       

3 个答案:

答案 0 :(得分:5)

使用“for each”循环时,不能在列表中使用remove。相反,您可以使用它在迭代器上调用remove:

Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()) {
    Integer integer = iterator.next();

    // ...check if you want to remove this one...

    iterator.remove();
}

如果您确实想要用“200”替换每个值,或者替换为其他值,那么构建新列表可能更有意义:

List<Integer> newList = new ArrayList<Integer>();

Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()) {
    Integer integer = iterator.next();

    newList.add(integer);

    iterator.remove();
}

答案 1 :(得分:3)

如果您在修改数组时迭代数组,那么行为应该是什么不清楚。

如果删除一个元素,如果它仍然被迭代怎么办?

该列表不会尝试猜测,而是抛出ConcurrentModificationException以导致错误,而不是通过意外行为传递。

一种解决方案是您可以迭代列表的浅表副本,然后修改原始列表

答案 2 :(得分:0)

您可以从正在使用的ArrayList中删除对象。我在我的游戏引擎中使用它,它可以工作。

请参阅http://code.google.com/p/game-engine-for-java/source/browse/src/com/gej/map/Map.java#350

for (int i = 0; i < objects.size(); i++) {
    GObject other = objects.get(i);
    if (other.isAlive()) {
        // Update it
    } else {
        // Else remove it
        objects.remove(i);
    }
}

您遇到的错误是这对for each循环不起作用。尝试正常的for循环,这应该可以解决您的问题。

将您的代码更改为此。

ArrayList<Integer> list =new ArrayList<Integer>();
ArrayList<Integer> remove = new ArrayList<Integer>();
list.add(100);
list.add(200);
list.add(300);
list.add(400);
// Mark to remove
for (int i=0; i<list.size(); i++){
    remove.add(list.get(i));
}
list.removeAll(remove);
remove.clear();
// adding 200 at the end because if added in the loop,
// it removes the 200 and adds every loop which causes
// unnecessary memory usage.
list.add(200);