Consider the following code snippet:
List<String> list = new LinkedList<>(); list.add("Hello"); list.add("My"); list.add("Son"); for (String s: list){ if (s.equals("My")) list.remove(s); System.out.printf("s=%s, list=%s\n",s,list.toString()); }
This leads to the conclusion:
s = Hello, list = [Hello, My, Son]
s = My, list = [Hello, Son]
Thus, the cycle was introduced only twice, and the third element "Son" is never visited. From the base code of the library, it seems that the hasNext() method in the iterator does not check the simultaneous modification, but only the size with respect to the next index. Since the size was reduced by 1 by calling remove() , the loop simply is not thrown again, but the ConcurrentModificationException is not thrown.
This is contrary to the iterator contract:
Fail-fast iterator list: if the list is structurally modified at any time after creating the Iterator, in any way other than through its own remove or add iterator list, the iterator list will throw a ConcurrentModificationException . Thus, in the face of simultaneous modification, the iterator is fast and clean, and does not risk arbitrary, non-deterministic behavior at an undetermined time in the future.
This is mistake? Again, the iterator contract is definitely not in dispute here - the list structure is structurally modified by something other than an iterator in the middle of the iteration.