java.util.ConcurrentModificationException异常详解
今天学习java集合的时候遇到了以下问题,下面是出现异常的代码
public class CollectionMapDemo {
public static void main(String[] args) {
Collection collection = new ArrayList();
Iterator it = collection.iterator();
collection.add("a");
collection.add("b");
while (it.hasNext()) {
// Object o = it.next();
String s = it.next().toString();
System.out.println(s);
}
}
}
运行结果是:
异常原因:在实现iterator之后对集合元素进行操作导致迭代器的modCount和expectedModCount的值不一致
让我们来看一下ArrayList实现iterator的源码
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
从以上代码可以看出开始时,expectedModCount(期望修改次数) 和 modCount(实际修改次数)是相同的,但是经过 collection.add("a"); collection.add("b");修改之后modCount(实际修改次数)已经变化,导致在最后执行checkForComodification方法时,出现ConcurrentModificationException异常,解决方法就是在实现iterator接口之前,完成对结合的操作
同理以下代码也会出错
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(2);
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
Integer integer = iterator.next();
if(integer==2)
list.remove(integer);
}
}
当调用了list.remove方法之后,modCount(实际修改次数)已经变化,同样也会出现ConcurrentModificationException异常。这里就可以调用实现了iterator自身的remove,在代码中就不会出错了。解决办法是list.remove()改为iterator.remove()