It does not throw exception ConcurrentModificationException
Because you aren't removing 1, you are removing the element at 1. ( remove(int)
vs remove(Object)
)
The iterator will only check for modification on a call to next()
and not hasNext()
, and the loop will exit after the call to hasNext()
because you have removed 2, the list is only one long and thus exits.
The remove(int)
method on List
removes the element at the specified position. Before you start your loop, your list looks like this:
[1, 2]
Then you start an iterator on the list:
[1, 2]
^
Your for
loop then removes the element at position 1, which is the number 2:
[1]
^
The iterator, on the next implied hasNext()
call, returns false
, and the loop terminates.
You will get a ConcurrentModificationException
if you add more elements to the list. Then the implicit next()
will throw.
As a note, from the Javadoc for ArrayList
from the JCF:
Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw
ConcurrentModificationException
on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.
This is probably actually a bug in the Oracle ArrayList
iterator implementation; hasNext()
does not check for modification:
public boolean hasNext() {
return cursor != size;
}
if you have a list of 3 like:
lis.add(1);
lis.add(2);
lis.add(3);
you will get ConcurrentModificationException in your case. PS: I have tried this!
It doesn't throw a ConcurrentModificationException because, as vandale said, the iterator only checks for comodification on next(). Here's a portion of the Iterator instance returned by an ArrayList:
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];
}
hasNext() simply looks to see if the cursor is pointing at the last index of the list. It doesn't check to see if the list was modified. Because of this you don't get an ConcurrentModificationException, it just stops iterating.