Let's see how, for example, the ArrayLists iterator is implemented:
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; }
Let's look at an example:
List list = new ArrayList(Arrays.asList(1, 2, 3, 4)); Iterator it = list.iterator(); Integer item = it.next();
Delete the first element
list.remove(0);
If we want to call it.remove() now, the iterator will remove number 2 because it now indicates that the field is lastRet .
if (item == 1) { it.remove();
That would be the wrong behavior! The iterator's contract states that remove() removes the last element returned by next() , but it cannot hold on to its contract if there are parallel modifications. Therefore, he prefers to be safe and excluded.
The situation may be even more complicated for other collections. If you change the HashMap , it can increase or decrease as necessary. At this time, the elements will fall into different buckets, and an iterator that stores a pointer to the bucket before the reboot is completely lost.
Note that iterator.remove() does not throw an exception on its own, as it can update both the internal state and the collection. A call to remove() on two iterators of the same collection of instances will throw, however, because it will leave one of the iterators in an inconsistent state.
source share