【问题标题】:How to fix java.util.ConcurrentModificationException error when trying traverse in ArrayList尝试在 ArrayList 中遍历时如何修复 java.util.ConcurrentModificationException 错误
【发布时间】:2012-05-19 17:56:16
【问题描述】:

如果满足条件,我正在尝试将新对象添加到我的 ArrayList 中。 但是当我尝试运行它时,它给了我这个 ConcurrentModificationExeption。希望你能帮助我:

public void addTaskCollection(Task t){ 
    ListIterator<Task> iterator = this.taskCollection.listIterator();
    if(this.taskCollection.isEmpty())
        this.taskCollection.add(t);
    while (iterator.hasNext()){
        if(t.isOverlapped(iterator.next()))
            this.taskCollection.add(t);
    }    
}

这是异常错误

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at Diary.addTaskCollection(Diary.java:36)
at Test.main(Test.java:50)
Java Result: 1

【问题讨论】:

标签: java exception


【解决方案1】:

维护两个迭代器。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Example_v3 {

     public static void main(String[] args) {
          List<String> list = new ArrayList<String>();

          // Insert some sample values.
          list.add("Value1");
          list.add("Value2");
          list.add("Value3");

          // Get two iterators.
          Iterator<String> ite = list.iterator();
          Iterator<String> ite2 = list.iterator();

          // Point to the first object of the list and then, remove it.
          ite.next();
          ite.remove();

          /* The second iterator tries to remove the first object as well. The object does
           * not exist and thus, a ConcurrentModificationException is thrown. */
          ite2.next();
          ite2.remove();
     }
}

【讨论】:

    【解决方案2】:

    重新格式化了来自 cmets 的 Truong 的回答:

    ListIterator<Task> iterator = this.taskCollection.listIterator();
    boolean marker = false;
    
    if(taskCollection.isEmpty())
      this.taskCollection.add(t);
    else {
      while (iterator.hasNext()) {
        if(iterator.next().isOverlapped(t) == false)
          marker = true;
      }
      if (marker == true)
        taskCollection.add(t);
    }
    

    【讨论】:

      【解决方案3】:

      您似乎遇到了竞争条件。多个线程正在访问/修改同一个集合。使用线程安全的 List 实现。

      此外,您不得在使用迭代器对其进行迭代时修改(添加/删除)集合。

      编辑

      ConcurrentModificationExeption 听起来 taskCollection 被多个线程同时访问和修改(如果您的程序是单线程或多线程,我们不能说您提供的代码段)。如果您在多个线程之间共享 taskCollection,请使用线程安全列表实现。

      但是,这里的错误实际上显然是由于您在获得迭代器的那一刻和使用该迭代器的那一刻之间向集合中添加了一个元素。要修复该问题,将临时列表中的新元素复制并在迭代结束时将它们全部添加一次。

      【讨论】:

      • 那么如何修改上面的arraylist,请赐教?
      • 问题在于您不能在使用迭代器迭代列表时修改列表...这就是为什么您必须复制它并修改副本的原因。
      • 首先,您没有足够的输入来说明该程序是单线程的。无论如何,我们都同意错误是由于迭代/修改造成的,您指出我的帖子不清楚是对的。所以我刚刚编辑了它。其次,这里是 ConcurrentModificationException 的 javadoc :“......通常不允许一个线程在另一个线程对其进行迭代时修改 Collection。通常,在这些情况下迭代的结果是不确定的......”
      • 你不知道它是多线程的。它很可能是单线程的
      • 你也不知道它是单线程的,这就是我所说的。我很抱歉我可能想暗示问题不是由于 iter./modif 引起的。事物。这很令人困惑。但是,即使修复了这个错误,ConcurrentModificationException 仍然可能发生,这取决于访问 taskCollection 的方式。见docs.oracle.com/javase/1.4.2/docs/api/java/util/…,这种异常的第一个原因是竞争条件,单线程环境中的迭代/修改仅排在第二位。
      【解决方案4】:

      将您的代码替换为:

      ListIterator<Task> iterator = this.taskCollection.listIterator();
      boolean marker = false;
      
      if(taskCollection.isEmpty())
          this.taskCollection.add(t);
      else {
         while (iterator.hasNext()) {
            if(iterator.next().isOverlapped(t) == false)
               marker = true;
         }
      }
      
      if (marker == true)
          taskCollection.add(t);
      

      避免 ConcurrentModificationException。

      【讨论】:

      • 您是否仍然收到 ConcurrentModificationException?
      • 是的,我尝试稍微更改您的代码以使其编译,但输出不正确。
      • 我终于做对了,但没有足够的权限来回答我的问题。如果可能,请帮助我将您的代码更改为我的代码,如下所示: ListIterator&lt;Task&gt; iterator = this.taskCollection.listIterator(); boolean marker = false; if(taskCollection.isEmpty()) this.taskCollection.add(t); else{ while (iterator.hasNext()){ if(iterator.next().isOverlapped(t) == false) marker = true; } if (marker == true) taskCollection.add(t); }
      • 因为您的回答与我的问题非常接近,所以我将您标记为正确答案。
      • 很奇怪,因为如果您注意到我的代码没有修改即被迭代的集合。最有可能在改变你的时候以某种方式恢复了你的原始代码。我建议您再次在您的问题中发布您的最新代码,然后我可以为您提供更好的帮助。
      【解决方案5】:

      复制数组并更改原始数组。

      【讨论】:

      • 尝试使用 Collections.copy(destiny, source) 复制。
      • 我尝试编码List&lt;Task&gt; tempCollection = this.taskCollection; ListIterator&lt;Task&gt; iterator = tempCollection.listIterator(); if(tempCollection.isEmpty()) taskCollection.add(t); while (iterator.hasNext()){ if(t.isOverlapped(iterator.next())) taskCollection.add(t); },但它不起作用
      • 也许你可以试试这个:boolean modifyReqd = false; for(Task task : this.taskCollection) { if() {//这里检查条件 modifyReqd = true;休息; } } if(modificationReqd) { this.taskCollection.add(t); }
      猜你喜欢
      • 2021-09-19
      • 2016-11-17
      • 2012-07-09
      • 2012-04-08
      • 2015-11-21
      • 2013-11-08
      • 2019-05-04
      • 1970-01-01
      • 2021-08-05
      相关资源
      最近更新 更多