java list java.util.ConcurrentModificationException

时间:2016-01-23 16:53:19

标签: java list

我有这种代码的和平。
我知道这必须给我ConcurrentModificationException
我必须使用迭代器或克隆列表或只是使用for循环。

问题是这段代码运行没有问题,ls.remove可以在0-2之间的任何索引上运行 现在如果我将 s.equals(“两个”)更改为 s.equals(“one”)或列表中除“两个”之外的任何其他内容“
我将始终按预期获得ConcurrentModificationException。

另外,如果我取消注释ls.add(“4”)行,无论 s.equals()是什么,我都会有ConcurrentModificationException。

并且我的问题是为什么会发生这种情况以及为什么下面的代码只对s.equals(“two”)运行良好而没有ConcurrentModificationException?

import java.util.*;
import java.util.List;

    public class Test {

    public static void main(String args[]) {

        List<String> ls = new ArrayList<>();

        ls.add("one");
        ls.add("two");
        ls.add("three");
        //ls.add("four");

        for(String s : ls) {
            if(s.equals("two")) {
                ls.remove(0);
                //ls.remove("three");
            }
        }

        System.out.println(ls.size());

    }

}

和输出

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at Test.main(Test.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at     sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.    java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

1 个答案:

答案 0 :(得分:1)

迭代时不得修改列表。迭代器可能(或可能不)失败,具体取决于实现。因此,删除部分列表中的某些元素可能有效,有些则可能无效。解决此问题的保存方法是使用迭代器remove方法,或使用CopyOnWriteArrayList或支持此类修改的任何其他集合。