Search code examples
javaiteratorjavac

Why doesn't the compiler spot certain causes of ConcurrentModificationException


It's very clear that this code is modifying a list during iteration.

public class ArrayIterator {

    public static void main(String[] args) {

        List<String> list = new LinkedList<>(Arrays.asList("A","B","C","D","E"));

        Iterator<String> it = list.iterator();
        while (it.hasNext())
        {
            list.remove(it.next());
        }

    }
}

And so we get the expected Exception

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
    at java.util.LinkedList$ListItr.next(LinkedList.java:888)
    at ArrayIterator.main(ArrayIterator.java:15)

Why isn't the compiler able to warn about this?


Solution

  • java.util.ConcurrentModificationException is a runtime exception. It may (or may not) occur. In some scenarios, you would expect a remove() to throw this exception while iterating on a collection, but depending on the number of elements and the position of the current element, the exception would not occur.

    For example, the following does not throw an exception:

    List<String> list = new LinkedList<String>(Arrays.asList("A", "B", "C", "D", "E"));
    Iterator<String> it = list.iterator();
    while (it.hasNext()) {
        String next = it.next();
        if(next.equals("D")) {
            list.remove(next);
        }
    }
    

    On the other hand, the following throws the exception:

    List<String> list = new LinkedList<String>(Arrays.asList("A", "B", "C", "D", "E"));
    Iterator<String> it = list.iterator();
    while (it.hasNext()) {
        String next = it.next();
        if(next.equals("C")) {
            list.remove(next);
        }
    }