Search code examples
javalinked-listpriority-queue

Why do I get a ConcurrentModificationException?


Why do I get a ConcurrentModificationException at the specified location in my code? I cannot figure out what I am doing wrong... The removeMin() method is being used to locate the min in the list pq, remove it, and return its value

import java.util.Iterator;
import java.util.LinkedList;

public class test1 {

    static LinkedList<Integer> list = new LinkedList<Integer>();

    public static void main(String[] args) {
        list.add(10);
        list.add(4);
        list.add(12);
        list.add(3);
        list.add(7);

        System.out.println(removeMin());
    }

    public static Integer removeMin() {
        LinkedList<Integer> pq = new LinkedList<Integer>();
        Iterator<Integer> itPQ = pq.iterator();

        // Put contents of list into pq
        for (int i = 0; i < list.size(); i++) {
            pq.add(list.removeFirst());
        }

        int min = Integer.MAX_VALUE;
        int pos = 0;
        int remPos = 0;

        while (itPQ.hasNext()) {
            Integer element = itPQ.next(); // I get ConcurrentModificationException here
            if (element < min) {
                min = element;
                remPos = pos;
            }
            pos++;
        }

        pq.remove(remPos);
        return remPos;
    }

}

Solution

  • An Iterator should not be considered usable once the Collection from which it was obtained is modified. (This restriction is relaxed for java.util.concurrent.* collection classes.)

    You are first obtaining an Iterator for pq, then modifying pq. Once you modify pq, the Iterator itPQ is no longer valid, so when you try to use it, you get a ConcurrentModificationException.

    One solution is to move Iterator<Integer> itPQ = pq.iterator(); to right before the while loop. A better approach is to do away with the explicit use of Iterator altogether:

    for (Integer element : pq) {
    

    Technically, the for-each loop uses an Iterator internally, so either way, this loop would only be valid as long as you don’t try to modify pq inside the loop.