Search code examples
javaconcurrentmodification

java generics runtime error.java.util.ConcurrentModificationException


I have the following example java generics code which I modified as per suggestion of people on StackOverflow.Now the compilation is going through.

import java.util.*;

public class GenericBox<T>
{

        private List<T> tList;
        private Iterator<T> itor;

        public GenericBox()
        {
                tList = new ArrayList<T>();
                itor = tList.listIterator();
        }

        public void insert(T element)
        {
                tList.add(element);
        }

        public T retrieve()
        {
                if(itor.hasNext())
                {
                        return itor.next();
                }
                return null;
        }

        public static void main (String [] args)
        {

                GenericBox <String> strbox = new GenericBox<String>();
                GenericBox <String> intbox = new GenericBox<String>();

                strbox.insert(new String("karthik"));
                strbox.insert(new String("kanchana"));
                strbox.insert(new String("aditya"));


                String s = strbox.retrieve();
                System.out.println(s);

                s = strbox.retrieve();
                System.out.println(s);

                s = strbox.retrieve();
                System.out.println(s);
        }
}

I am getting the following runtime error.

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
    at java.util.ArrayList$Itr.next(ArrayList.java:791)
    at GenericBox.retrieve(GenericBox.java:24)
    at GenericBox.main(GenericBox.java:40)

Solution

  • This has nothing to do with generics, and everything to do with the fact that you're modifying a collection directly (in insert) and then trying to use an iterator which was created before the insertion. Don't do it.

    From the docs of ArrayList:

    The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

    If you must keep the iterator around, use that to add a new value instead:

    private ListIterator<T> itor; // Not just Iterator<T>; you need the add method
    
    public void insert(T element)
    {
        itor.add(element);
    }
    

    It would be better not to keep the iterator around though - it's very rarely a good idea to use an iterator other than for a direct loop.