为什么我得到java.util.ConcurrentModificationException?

时间:2013-08-26 09:05:06

标签: java exception

当我运行以下代码时:

    import java.util.LinkedList;

    class Tester {
      public static void main(String args[]) {
        LinkedList<String> list = new LinkedList<String>();
        list.add(new String("suhail"));
        list.add(new String("gupta"));
        list.add(new String("ghazal"));
        list.add(new String("poetry"));
        list.add(new String("music"));
        list.add(new String("art"));

        try {
            for(String s : list) {
            list.add(0,"art");
            list.remove(6);
            System.out.println(list);
        }
        }catch(Exception exc) {
            exc.printStackTrace();
        }

    }
}

我得到一个例外:

java.util.ConcurrentModificationException
    at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
    at java.util.LinkedList$ListItr.next(Unknown Source)
    at Tester.main(Tester.java:14)

为什么我会收到此异常?

编辑:tmpList是一个LinkedList,其每个节点都包含DepConfAttr类型的对象。我在内存(最高内存优先)的基础上对tmpList进行排序,这是DepConfAttr对象的属性之一。

以上代码反映了我想通过以下代码实现的目标

int size = tmpList.size();
        int elementBC = 0; // element being checked
        int startIndex = 1;
        for (DepConfAttr dca : tmpList) {
            long maxMem = dca.getMemory(); // Let this be the maximum memory
            for(int i = startIndex ; i < size ; i++) {
                DepConfAttr dcaTmp = tmpList.get(i);
                if(maxMem < dcaTmp.getMemory()) {
                    tmpList.add(elementBC, dcaTmp);
                    tmpList.remove(i+1);
                    maxMem = tmpList.get(elementBC).getMemory();                        
                }
            }
            elementBC++;
            startIndex++;
            size--;
        }

7 个答案:

答案 0 :(得分:11)

  

为什么我会收到此异常?

除了通过迭代器之外,你正在从列表中删除一个项目,同时迭代它。当你迭代它时,你也会添加到列表中。

你在这里尝试实现的目标并不是很清楚,但除了并发集合之外,当你尝试这样做时,你总会遇到异常。

一个常见的解决方法是首先创建列表的副本并对其进行迭代,然后修改原始列表。

答案 1 :(得分:2)

当您遍历列表时,无法从中删除项目。这样做会导致异常。

执行:

int size = list.size();
for (int i = 0 ; i< size ; i++) {
   list.add(0,"art");
   list.remove(6);
   System.out.println(list);
}

答案 2 :(得分:1)

问题是,当List试图在其上运行时,您正在直接修改Iterator。下次你告诉Iterator迭代(隐式地,在for循环中)时,它会注意到List已从其下面更改并抛出异常。

相反,如果您需要在遍历时修改列表,请明确抓取Iterator并使用它:

List<String> list = ....
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String s = iterator.next(); // must be called before you can call iterator.remove()
    iterator.remove();
}

在此过程中你仍然无法插入List,这不会让你删除任意元素,只删除当前元素。

答案 3 :(得分:0)

问题是在对列表使用隐式迭代器时对列表进行更改。对于引用的代码,最简单的解决方案是根本不使用Iterator:

for(int i=0; i<list.size(); i++) {
  list.add(0,"art");
  list.remove(6);
  System.out.println(list);
}

您可能需要发布更实际的代码,以获得最佳解决方案的建议。如果要在迭代列表时删除当前项,请使用显式迭代器循环,并使用Iterator的remove()方法。在其他情况下,最好的解决方案是为循环内部的更改形成计划,但之后执行它。例如,在循环列表中构建一个removeList,其中包含要删除的元素的索引列表。在removeList的单独循环中,从列表中删除这些元素。

答案 4 :(得分:0)

因为您同时(同时)修改和迭代集合。 Java不喜欢这个

由于您实际上并未使用s,因此可以使用标准for循环

for(int i=0; i< list.size(); i++) {
      list.add(0,"art");
      list.remove(6);
      System.out.println(list);
}

答案 5 :(得分:0)

当您尝试通过另一个线程或循环尝试修改(添加/删除)列表内容时,会抛出ConcurrentModificationException。

您可以尝试使用ConcurrentLinkedQueue或John声明复制并在迭代中修改原始文件。

Queue<String> list = new ConcurrentLinkedQueue<String>();

list.add("suhail");
list.add("gupta");
list.add("ghazal");
list.add("poetry");
list.add("music");
list.add("art");

int size = list.size();

for(int i = 0; i < size; i++){
    list.add("art");
    list.remove("art");
    System.out.println(list);
}

答案 6 :(得分:-1)

您需要明确使用迭代器才能工作。例如:

 Iterator<String> iter = li.iterator();
   while(iter.hasNext()){
    if(iter.next().equalsIgnoreCase("some value"))
      iter.remove();
    }
   }

此处有更多信息:http://www.coderanch.com/t/233932/threads/java/deal-Concurrent-Modification-Exception但只是谷歌例外,你会发现很多例子。