Question

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)
Was it helpful?

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.

OTHER TIPS

You get this exception because the list has been modified between the creation of the iterator and its usage. You should only call iterator() when you actually want to iterate over the list. Not before. And you shouldn't store the iterator in an instance field. Only in a local variable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top