user2230870
user2230870

Reputation: 11

Collections: ConcurrentModificationException

Why am I getting this ConcurrentModificationException in the following code?

public static ArrayList<ArrayList<String>> buildPath(String s, String e, HashMap<String, ArrayList<String>> visited) {
    ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
    ArrayList<ArrayList<String>> temp = new ArrayList<ArrayList<String>>();
    ArrayList<String> tmp = new ArrayList<String>();
    tmp.add(e);
    ret.add(tmp);
    boolean needStop = false;
    while (true) {
        for (ArrayList<String> al : ret) { //concurrent exception
            ArrayList<String> pre_words = visited.get(al.get(al.size() - 1));
            for (String pre_word : pre_words) {
                if (pre_word.compareTo(s) == 0) {
                    needStop = true;
                }
                if (needStop && pre_word.compareTo(s) != 0) {
                    continue;
                }
                ArrayList<String> toadd = new ArrayList<String>(al);
                toadd.add(pre_word);
                temp.add(toadd);

            }
        }
        ret = temp;
        if (needStop) {
            for (ArrayList<String> l : ret) {
                Collections.reverse(l);
            }
            return ret;
        }
    }
}

If I make the following change the program runs correctly:

From:

for(ArrayList<String> al : ret) {

to:

for(int i =0; i <ret.size() ; i++) {
    ArrayList<String> al = ret.get(i);

Upvotes: 1

Views: 197

Answers (2)

Boris the Spider
Boris the Spider

Reputation: 61128

A ConcurrentModificationException occurs when you modify a Collection while looping, this is because this behaviour is not supported.

Your loop is over ret

for(ArrayList<String> al : ret)

You modify tmp

temp.add(toadd);

You then later assign tmp to ret

ret= temp;

The next time you loop (the big loop while(true)) you modify the Collection you get a ConcurrentModificationException.

The reason you don't get that when you loop manually

for(int i =0; i <ret.size() ; i++)

Is because you are not using an Iterator which is implicitly used in the enhanced-foreach-loop. If you do not use an Iterator then your dodgy code cannot be checked...

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691655

You're adding elements to a list while iterating over it using an iterator. This is what causes this exception.

Iterators of non-concurrent collections are fail-fast: they throw such an exception as soon as they notice that the collection has been modified during the iteration.

Upvotes: 1

Related Questions