a ConcurrentModificationException
can is thrown in situations when you're trying to modify a collection while it can't be modified. A simple example of this happening is code such as this:
List<Integer> l = new ArrayList<>();
...
Iterator<Integer> iter = l.iterator();
l.remove(0);
iter.next();
Here we've created an iterator, and then removed the first element of the ArrayList
. This action invalidates the iterator, and it isn't clear which element it should now return. So the call to iter.next()
throws a ConcurrentModificationException
.
You can see this in ArrayList's Iterator implementation (link):
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];
}
As you can see, the first thing a call to next()
does is check whether the state of this Iterator
is still valid by checking whether the ArrayList
has been modified.
But when Im practice this on my IDE, I see this exception is thrown
only when removing the first or last element.
That's not the case. Any modification of the list's structure will throw the exception. Let's try replacing the l.remove(0)
line with something different.
How about removing an item from the middle - l.remove(3)
? It throws an exception.
How about l.add(3)
or l.add(1,1)
? They both throw an exception.
How about l.remove(0)
, followed by l.add(0)
. This maintains the list's length, so it should be fine, right? No. It also throws an exception.
The only modification we're allowed is replacing an element in-place using a set()
call such as set(1,1)
because it doesn't affect the list's structure. This has nothing to do with the first or last element of the list.