在Android Studio导入Eclipse工程,执行退出App代码报错:java.util.ConcurrentModificationException at java.util.ArrayList$Itr.next(ArrayList.java:831)
List<Activity> activityStack = new ArrayList<Activity>();
// 移除Activity组 for (Activity activity : activityStack) { if (activity != null) { activity.finish(); } }
究其原因,是因为重写了activity.finish() 方法,在方法里面执行了activityStack.remove(this);即触发了ArrayList的remove方法,
而remove方法只是修改了源码内部属性modCount的值,并没有修改expectedModCount,导致modCount和expectedModCount的值的不一致性,当next()时则抛出ConcurrentModificationException异常
因此使用Iterator遍历集合时,不要改动被迭代的对象,可以使用 Iterator 本身的方法 remove() 来删除对象,Iterator.remove() 方法会在删除当前迭代对象的同时维护modCount和expectedModCount值的一致性。
另附 JDK java.util. AbstractList类中关键源码部分
java.util. AbstractList的内部类Itr的源码如下:
private class Itr implements Iterator {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
checkForComodification(); //检测modCount和expectedModCount的值!!
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet == -1)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet); //执行remove的操作
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount; //保证了modCount和expectedModCount的值的一致性,避免抛出ConcurrentModificationException异常
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount) //当modCount和expectedModCount值不相等时,则抛出ConcurrentModificationException异常
throw new ConcurrentModificationException();
}
}
再看一下ArrayList 的 remove方法
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 void fastRemove(int index) {
modCount++; //只是修改了modCount,因此modCount将与expectedModCount的值不一致
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
回过头去看看java.util. AbstractList的next()方法
public E next() {
checkForComodification(); //检测modCount和expectedModCount的值!!
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount) //当modCount和expectedModCount值不相等时,则抛出ConcurrentModificationException异常
throw new ConcurrentModificationException();
}
}