What happens in this situation is you are removing the second list element.
List<String> list = new ArrayList<String>
(Arrays.asList("noob1", "noob2", "noob3", "noob4"));
System.out.println(list);
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String str = iterator.next();
if (str.equals("noob3")) {
System.out.println("Checking "+str);
list.remove(str);
}
}
System.out.println(list);
prints
[noob1, noob2, noob3, noob4]
Checking noob1
Checking noob2
Checking noob3
[noob1, noob2, noob4]
By removing the second last element you have reduced the size to the number of elements which you have iterated over.
// from ArrayList.Itr
public boolean hasNext() {
return cursor != size;
}
This causes the loop to exit early before the concurrent modifcation check is performed in next()
. If you remove any other element next()
is called and you get a CME.
BTW Something which also bypasses the check is
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String str = iterator.next();
System.out.println("Checking "+str);
if (str.equals("noob2")) {
list.remove("noob1");
list.remove("noob3");
}
}
as long as the size of the collection is the same as the index it is up to, the check is not performed.