1

为什么下面的代码会抛出 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);
}       
4

3 回答 3

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();
}
于 2012-10-09T05:15:53.707 回答
3

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

如果你删除了一个元素,它还应该被迭代吗?

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

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

于 2012-10-09T05:17:59.010 回答
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);
于 2012-10-09T05:23:07.073 回答