1.Iterator迭代,原始结构发生改变; 举例如下
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator<String> iterator = arrayList.iterator(); // expectedModCount = modCount = 3 ;
while(iterator.hasNext()) {
String next = iterator.next(); // modCount=3;>>modCount != expectedModCount
arrayList.remove(next); // modCount=4;>>
}
当执行arrayList.iterator()时,首先如下生成一个iterator
public Iterator<E> iterator() {
return new Itr();
}
Itr源码如下:类在初始化时,会记录expectedModCount的值为modCount的值,modCount是在AbstractList中定义的,ArrayList初始化时,其值为0,在arrayList执行add(E)方法时,modCount自增。所以在执行arrayList.iterator()语句之后,expectedModCount = modCount = 3;
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();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
如下实例代码,首次执行iterator.next()时,modCount=3,所以在checkForComodificaion方法校验时,并没有出现异常,第二次执行该语句时,因为之前的arrayList.remove(next);语句执行过程中,修改了modCount的值,所以,modCount != expectedModCount成立,导致抛出异常。
while(iterator.hasNext()) {
String next = iterator.next(); // modCount=3;>> modCount != expectedModCount
arrayList.remove(next); // modCount=4;>>
}
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;
}
arrayList是可以移除Null元素的。并且,每次移除时,都需要执行fastRemove(index);方法,该方法源码如下:
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
}
2. for循环迭代,元素个数!=2的情况下
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
for(String s:arrayList) {
arrayList.remove(s);
}
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("1");
arrayList.add("2");// modCount = 2;
for(String s:arrayList) { //iterator()-->next()--> excpetionModCount=2 ;iterator()-->next()-->excpetionModCount!=modCount
arrayList.remove(s); //modCount = 3;
}
arrayList.remove(E);源码如(Iterator迭代方式中展示),注意fastRemove()方法的源码:
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
}
注意elementData[--size]=null,则将最后一个元素置为null,那么当程序再次进入for循环中时,执行iterator.hasNext()方法,源码如下
public boolean hasNext() {
return cursor != size;
}
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];
}
cursor完成自增操作,所以第二次进入hasNext()方法时,cursor = 1, 而size值由arrayList.remove(E)中自减,最后,导致cursor = size;所以,没有抛出异常,而是正常退出程序。