Iterator
正常的情况
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer next = iterator.next();
System.out.println(next);
}
可以正常进行遍历
如果在便利的时候remove了一下
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer num = iterator.next();
if (num.equals(1)) {
list.remove(num);
}
}
异常名字 ConcurrentModificationException:同步修改异常,字面上的理解就是在迭代器在迭代元素的时候,原来arraylist数组发生了变化,这样就导致了异常。Iterator<Integer> iterator = list.iterator();
源码:
public Iterator<E> iterator() {
return new Itr();
}
Itr是一个内部类,它的部分源码:
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; // expectedModCount 就是创建一个迭代器的时候,list数组才开始到现在的修改次数,后者是实际的修改次数
// 在最开始的时候,两个是一样的
初始化一个Iterator以后,需要使用next
public E next() {
checkForComodification();
int i = cursor; // cursor就是当前需要获取的元素
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1; // cursor继续指向下一个元素
return (E) elementData[lastRet = i]; // 返回地3行cursor的元素
}
final void checkForComodification() {
if (modCount != expectedModCount) // 看下方函数
throw new ConcurrentModificationException();
}
list.remove调用
public E remove(int index) {
rangeCheck(index);
modCount++; // modCount 被修改了,与iterator的expectedModCount就不一致了
E oldValue = elementData(index);
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
return oldValue;
}
再看一下iterator.remove()
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet; // cursor 往前一个单位
lastRet = -1; // 这个地方修改了lastRet,在看函数的第2行,会有异常,但是为什么没有呢?
expectedModCount = modCount; //重置expectedModCount
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
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]; // 这个时候重新修改了lastRet,所以不会在remove()函数里面报异常
}
从上面源码可以看出,如果连续两次iterator.remove(),那么还是会报错