使用for(Event e: eventList)循环删除eventList时,报错"Exception in thread "main" java.util.ConcurrentModificationException";
使用for(Event e: new ArrayList<Event>(eventList))循环删除eventList时,成功;
public class Controller {
private List<Event> eventList = new ArrayList<Event>();
public void addEvent(Event c){
eventList.add(c);
}
public void run(){
while(eventList.size()>0)
for(Event e: eventList){//ArrayList<Event>(eventList)
if(e.ready()){
System.out.println(e);
e.action();
eventList.remove(e); //注掉该行代码无运行错误了
//eventList.add(e);
}
}
}
}
方式一:foreach迭代循环,会调用内部类iterator的next方法,和hasNext()方法,iterator初始化时会将expectedModCount 初始化为modCount;next方法会执行checkForComodification()检查;
private class Itr implements Iterator<E> {
/**
* Index of element to be returned by subsequent call to next.
*/
int cursor = 0;
/**
* Index of element returned by most recent call to next or
* previous. Reset to -1 if this element is deleted by a call
* to remove.
*/
int lastRet = -1;
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
public E next() {
checkForComodification();
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
而在循环层面,eventList.remove(e)只会增加modCount值,不会改变expectedModCount的值,请看ArrayList.class中的remove(Object o)代码,所以下次循环判断时,next方法中checkForComodification()检查失败报错;
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
方式二:每次for循环判断条件,都会动态新创建一个指向eventList的ArrayList,这样每次expectedModCount都被初始化为modCount;检查不会出问题;