Why doesn't this code throw a ConcurrentModificationException
? It modifies a Collection
while iterating through it, without using the Iterator.remove()
method, which is meant to be the only safe way of removing.
List<String> strings = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String string : strings)
if ("B".equals(string))
strings.remove("B");
System.out.println(strings);
I get the same result if I replace the ArrayList
with a LinkedList
. However if I change the list to ("A", "B", "C", "D)
or just ("A", "B")
I get the exception as expected. What is going on? I am using jdk1.8.0_25
if that is relevant.
EDIT
I've found the following link
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4902078
The relevant section is
See Question&Answers more detail:osThe naive solution is to add comodification checks to hasNext in AbstractList, but this doubles the cost of comodification checking. It turns out that it is sufficient to do the test only on the last iteration, which adds virtually nothing to the cost. In other words, the current implementation of hasNext:
public boolean hasNext() { return nextIndex() < size; }
Is replaced by this implementation:
public boolean hasNext() { if (cursor != size()) return true; checkForComodification(); return false; }
This change will not be made because a Sun-internal regulatory body rejected it. The formal ruling indicated that the change "has demonstrated the potential to have significant compatibility impact upon existing code." (The "compatibility impact" is that the fix has the potential to replace silent misbehavior with a ConcurrentModificationException.)