6

当我运行以下代码时:

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

7 回答 7

12

为什么我会收到此异常?

您正在从列表中删除一个项目,而不是通过迭代器,同时迭代它。在迭代列表时,您也会添加到列表中。

目前还不清楚您要在这里实现什么,但除了并发集合之外,当您尝试这样做时,您总是会遇到异常。

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

于 2013-08-26T09:10:00.423 回答
2

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

做:

int size = list.size();
for (int i = 0 ; i< size ; i++) {
   list.add(0,"art");
   list.remove(6);
   System.out.println(list);
}
于 2013-08-26T09:10:21.920 回答
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这个过程中,这不会让你删除任意元素,只删除当前元素。

于 2013-08-26T09:10:24.190 回答
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);
}
于 2013-08-26T09:16:21.457 回答
0

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

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

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

于 2013-08-26T09:12:38.233 回答
0

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

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

for(int i=0; i< list.size(); i++) {
      list.add(0,"art");
      list.remove(6);
      System.out.println(list);
}
于 2013-08-26T09:14:02.930 回答
-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但只是谷歌异常,你会发现很多例子。

于 2013-08-26T09:10:24.383 回答