AbstractList 迭代器认为集合应该返回的修改值,如果和期望的值不一致,那么迭代器检测到了并发修改 protected transient int modCount = 0; List迭代时定义了期望的修改值: int expectedModCount = modCount; 判定迭代是否结束条件: 迭代器的 next()方法在调用时会检测期望值与集合修改值是否一致
AbstractList<E>
定义了一个modCount属性。
protected transient int modCount = 0;
解释:
这个字段被用于 iterator 和 list iterator , 如果这个值被意外的修改, 这个迭代器将会抛出一个
ConcurrentModificationException异常,这提供了 失败快速 行为,在迭代期间面对并发修改。
适应范围:
{@code next}, {@code remove}, {@code previous},
{@code set} or {@code add}
ArrayList<E>
add(E e)方法, 对 modCount字段维护,每次新增元素 + 1
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
remove( ) 移除:
public E remove(int index) {
rangeCheck(index);
modCount++;
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;
}
迭代器迭代过程中对 modCount进行检查
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;
Itr() {}
// 判断是否退出迭代的条件
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
// 检查modCount
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() {
// 集合的modCount与期望值是否一致
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}