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