1. 问题:
ArrayList和LinkedList在循环读取时调用add和remove方法会抛出异常ConcurrentModificationException,看如下代码:
public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); list.add("4"); System.out.println("add item"); } }
运行结果如下:
2. 原因:
查看JDK源码就会发现问题是出现在next()函数这里,该函数会对list的ModCount进行校验,判断是否修改,如果大小不一样就会抛出如上异常,对于list的add和removed方法都会执行modcount++,但是expectedModCount大小不会改变。
ArrayList中的方法add和remove方法,操作这个方法会对ModCount进行加1操作
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
ArrayList没有重写Next方法,使用AbstractList的next方法,同时expectedModCount是AbstractList的一个友好型变量,当调用hashNext方法时会对该变量进行初始化,以后再对List进行修改都不会改变该值(int为基本类型)
int expectedModCount = modCount;
public E next() {
checkForComodification();
try {
E next = get(cursor);
lastRet = cursor++;
returnnext;
} catch(IndexOutOfBoundsException e) {
checkForComodification();
thrownew NoSuchElementException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
接下来看一下Linkedlist,LinkedList是重写了next()方法,具体如下:
public E next() {
checkForComodification();
if (nextIndex == size)
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.element;
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
以上源码都是基于JDK1.6,如有不妥地方,欢迎指教