【问题标题】:java.util.ConcurrentModificationException when modifying list修改列表时出现 java.util.ConcurrentModificationException
【发布时间】:2013-12-05 14:36:47
【问题描述】:

我正在尝试使用 App Engine 删除我的数据库中的一些文件并进行对象化。这是我有异常的一段代码:

for(SottoCategoria sc: lsc){
      List<Key<Dispensa>> ld2=sc.getDispense();
      if(ld2!=null){
         for(Key<Dispensa> kd : ld2){ // <---- Exception!!
            if(kd.equals(k)){
                sc.removeDispensa(k);
                ofy().save().entity(sc).now();
                                    break;
            }
        }
    }
}

这是从列表中删除的方法:

public void removeDispensa(Key<Dispensa> k ){
    Iterator<Key<Dispensa>> kIter = dispense.iterator();
    while(kIter.hasNext()) {
        Key<Dispensa> kk = kIter.next();
        System.out.println(kk.equals(k));
        if(kk.equals(k)){
            kIter.remove();
            break;
        }
    }

}

我该如何解决?谢谢!

编辑:

我解决了在循环中插入一个简单的中断,因为在 Sottocategoria 中只能是我想要删除的一种分配!

【问题讨论】:

  • for(Key&lt;Dispensa&gt; kd : ld2){,在第一个代码中,为什么需要那个循环?
  • 因为我有许多 Dispensa 项目的子类别。因此,如果我需要删除一个项目 Dispensa,我必须为每个子类别循环每个项目 Dispensa 列表。
  • 我认为在这两种情况下循环都在同一个列表上。
  • Nono.. 但在其他项目中,我认为您使用迭代器来解决此类问题。我说的对吗?

标签: java google-app-engine objectify


【解决方案1】:

ConcurrentModificationException 发生是因为您在迭代列表时尝试删除列表的一部分。尝试使用带索引的 for 循环或创建迭代器。

for 循环示例:

    for(int i = 0; i<dispense.size();i++) {
        System.out.println(dispense.get(i).equals(k));
        if(dispense.get(i).equals(k)){
            dispense.remove(i);
            break;
        }
    }

示例迭代器:

    Iterator<Key<Dispensa>> It = dispense.iterator();
    while(It.hasNext()) {
        Key<Dispensa> kk = It.next();
        System.out.println(kk.equals(k));
        if(kk.equals(k)){
            dispense.remove(kk);
            break;
        }
    }

【讨论】:

  • 你的循环例子给了我解决问题的想法!!谢谢!
【解决方案2】:

迭代器更适合这种用例。

这是一个例子:

public void removeDispensa(Key<Dispensa> k ){
    Iterator<Dispensa> kIter = k.iterator();
    while(kIter.hasNext()) {
        Dispensa kk = kIter.next();
        System.out.println(kk.equals(k));
        if(kk.equals(k)){
            kIter.remove();
        }
    }
}

【讨论】:

  • 您的 remove() 为空。
  • 没错,没有参数传入。它指示Iterator删除它的当前项。
  • 不。它从您正在迭代的列表中删除。我建议你阅读 Iterators :) 顺便说一下,你写的答案不会编译,因为 .remove() 不带参数。
  • 我不必阅读 oracle 文档。迭代器类中的 .remove() 函数不带参数,但看看我的 remove(kk) 前面是什么;我从分配列表中删除 kk ;) docs.oracle.com/javase/7/docs/api/java/util/List.html 这个删除需要参数。
【解决方案3】:

您不能修改正在迭代的列表。

【讨论】:

    【解决方案4】:

    尝试使用List.iterator() 来避免此异常。

    ConcurrentModificationException - 如果方法检测到对象的并发修改是不允许的,则该异常可能会抛出。使用迭代器时不会发生这种情况。使用迭代器遍历集合是遍历集合的最安全和最快的方法

    【讨论】:

      【解决方案5】:

      你的问题是因为你试图修改你正在读取的同一个数组,所以为了避免这个问题,你必须复制你的数组并迭代重复的数组并在好的数组中执行操作。

      如果您需要代码方面的帮助,请告诉我

      【讨论】:

      • Rafa:请避免批准对您的答案进行糟糕的修改。用户 Finga officiel 试图在您的答案中插入他自己的问题,但出于某种原因,您批准了它。
      • @HovercraftFullOfEels 感谢您的信息!是的,我错误地批准了...对不起!
      猜你喜欢
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-27
      • 1970-01-01
      • 2015-08-15
      • 2013-08-16
      相关资源
      最近更新 更多