当使用foreach或Iterator迭代器遍历集合时,同时调用迭代器自身以外的方法修改了集合的结构,例如调用集合的add和remove方法时,就会报ConcurrentModificationException。
但是,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ​​​ConcurrentModificationException​​*。例如:

ArrayList<String> list = new ArrayList<>();
list.add("安琪拉");
list.add("妲己");
list.add("嬴政");
list.add("项羽");

//以下代码没有发生ConcurrentModificationException异常
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String str = iterator.next();

if("嬴政".equals(str)){
list.remove(str);
}
}

为什么呢?

想要知道原因 必须清楚一点 就是在 迭代器调用时 next()会触发并发修改异常

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() {
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();
}
}

而在删除倒数第二个元素时 会导致size减少 不会再去执行next() 看源码

ArrayList<String> list = new ArrayList<>();
list.add("安琪拉");
list.add("妲己");
list.add("嬴政");
list.add("项羽");

//以下代码没有发生ConcurrentModificationException异常
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String str = iterator.next();

if("嬴政".equals(str)){
//注意这个 remove() 调用后
list.remove(str);
}
}
//会调用ArrayList 此方法 因为 o不为null 执行else
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;
}

//调用了此方法 删除了 嬴政
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 将size -1
elementData[--size] = null; // clear to let GC do its work
}
//因此 循环回去之后 再进行校验 再次调用此hasNext()
while(iterator.hasNext()){
String str = iterator.next();

if("嬴政".equals(str)){
//注意这个 remove() 调用后
list.remove(str);
}
}

public boolean hasNext() {
//因为size 已经减-1 与下标的值相同 返回false 结束迭代器遍历 不会再执行next() 因此不会报错
return cursor != size;
}