在列表中,添加或删除被视为修改。在您的情况下,您进行了 5 次修改(添加)。
'for each' 循环的工作方式如下,
1.It gets the iterator.
2.Checks for hasNext().
public boolean hasNext()
{
return cursor != size(); // cursor is zero initially.
}
3.如果为真,则使用 next() 获取下一个元素。
public E next()
{
checkForComodification();
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
final void checkForComodification()
{
// Initially modCount = expectedModCount (our case 5)
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
重复步骤 2 和 3 直到 hasNext() 返回 false。
如果我们从 list 中删除一个元素,它的大小会减小并且 modCount 会增加。
如果我们在迭代时移除一个元素,modCount != expectedModCount 会得到满足并抛出 ConcurrentModificationException。
但是删除倒数第二个对象很奇怪。让我们看看它在您的情况下是如何工作的。
最初,
cursor = 0 size = 5 --> hasNext() succeeds and next() also succeeds
without exception.
cursor = 1 size = 5 --> hasNext() succeeds and next() also succeeds
without exception.
cursor = 2 size = 5 --> hasNext() succeeds and next() also succeeds
without exception.
cursor = 3 size = 5 --> hasNext() succeeds and next() also succeeds
without exception.
In your case as you remove ‘d’ , size gets reduced to 4.
cursor = 4 size = 4 --> hasNext() does not succeed and next() is
skipped.
In other cases, ConcurrentModificationException will be thrown as modCount != expectedModCount.
In this case, this check does not take place.
If you try to print your element while iterating, only four entries will be printed. Last element is skipped.
Hope I made clear.