讓我們來看看如何,例如,ArrayLists
的迭代器來實現:
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
public E next() {
checkForComodification();
int i = cursor;
if (i >= size) throw new NoSuchElementException();
// ...
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
// ...
ArrayList.this.remove(lastRet);
// ...
cursor = lastRet;
lastRet = -1;
}
讓我們來看一個例子:
List list = new ArrayList(Arrays.asList(1, 2, 3, 4));
Iterator it = list.iterator();
Integer item = it.next();
我們刪除第一個元素
list.remove(0);
如果我們現在想要調用it.remove()
,迭代器將刪除number 2因爲這是lastRet
指向的字段。
if (item == 1) {
it.remove(); // list contains 3, 4
}
這將是不正確的行爲!迭代器的合約指出remove()
刪除next()
返回的最後一個元素,但在併發修改情況下無法保留其合約。因此它選擇安全並拋出異常。
其他館藏的情況可能更加複雜。如果您修改HashMap
,則可能會根據需要增加或減少。那時候,元素將落入不同的桶中,並且迭代器保持指向桶的指針,之後重新刷新將完全丟失。
請注意iterator.remove()
本身並沒有拋出異常,因爲它能夠更新這兩個它自己的內部狀態和集合。然而,在相同實例集合的兩個迭代器上調用remove()
會拋出,因爲它會使其中一個迭代器處於不一致狀態。
對於downvoter:請不要只是downvote答案,請解釋你看到什麼是錯的。我會非常感激。 –
真的,對於下流者,請告訴我什麼是錯的,或者你認爲我應該改變什麼。如果我錯了,請糾正我。我很好奇。 –