1

为什么我ConcurrentModificationException在下面的代码中得到这个?

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;
        }
    }
}

如果我进行以下更改,程序将正确运行:

从:

for(ArrayList<String> al : ret) {

至:

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

2 回答 2

1

您在使用迭代器对其进行迭代时将元素添加到列表中。这就是导致此异常的原因。

非并发集合的迭代器是快速失败的:一旦他们注意到集合在迭代期间被修改,它们就会抛出这样的异常。

于 2013-08-31T22:59:58.507 回答
1

AConcurrentModificationException在您修改Collectionwhile 循环时发生,这是因为不支持此行为。

你的循环结束了ret

for(ArrayList<String> al : ret)

你修改tmp

temp.add(toadd);

然后您稍后分配tmpret

ret= temp;

下次你循环(大循环while(true))你修改Collection你得到一个ConcurrentModificationException.

手动循环时没有得到它的原因

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

是因为您没有使用Iterator在增强的 foreach 循环中隐式使用的 an 。如果您不使用,Iterator则无法检查您的狡猾代码...

于 2013-08-31T23:00:40.743 回答