List<Person> first = new ArrayList<Person>();
Person p1=new Person("p1", 1);
Person p2=new Person("p2", 2);
Person p3=new Person("p3", 3);
first.add(p1);
first.add(p2);
first.add(p3);
for(Person p: first)
{
first.remove(p);
}
The above code will throw ConcurrentModificationException
Now remove the following code
first.add(p3);
And re-execute the code...
Now you'll see that no exception will be thrown...
What's the reason behind this?
Actually for-each loop uses Iterator behind the scenes
which gets converted to the following
Iterator i = first.iterator();
while(i.hasNext())
{
Person px = (Person)i.next();
first.remove(px);
}
In case of two elements, here are the steps that are followed
- Iterator is created
- hasNext returns true
- .next method returns the first element of the list
- First element is removed. Now list contains only 1 element.
- As iterator has already traversed one element and also list has 1 element, hasNext method will return false
- Hence the loop terminates.
- Iterator is created
- hasNext returns true
- .next method returns the first element of the list
- First element is removed. Now list contains 2 elements.
- As iterator has already traversed one element and list has 2 elements, hasNext method will return true
- control will enter the loop
- .next method will see that iterator has been modified and hence throw a ConcurrentModificationException