在ArrayList的foreach循环里面添加时ConcurrentModificationException的 [英] ConcurrentModificationException when adding inside a foreach loop in ArrayList

查看:240
本文介绍了在ArrayList的foreach循环里面添加时ConcurrentModificationException的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想利用与ArrayList中的foreach循环的,但是当我使用它,它给我的错误,但是当我使用正常的循环,它完美的作品,可能是什么问题?

在code是在这里:

 的(对P2:R){
    如果((p2.getFirstElm()== p.getSecondElm())及&放大器;!(p2.getFirstElm()= p2.getSecondElm()))
        R.add(双新(p.getFirstElm(),p2.getSecondElm()));
    否则如果((p2.getSecondElm()== p.getFirstElm())及&放大器;!(p2.getFirstElm()= p2.getSecondElm()))
        R.add(双新(p2.getFirstElm(),p.getSecondElm()));    //其他
    //有在R没有对传递
}

这是不工作的循环,而这里是工作的一个:

 的for(int i = 0; I< R.size();我++){
    如果((R.get(ⅰ).getFirstElm()== p.getSecondElm())及&放大器;!(R.get(ⅰ).getFirstElm()= R.get(ⅰ).getSecondElm()))
        R.add(新对(p.getFirstElm(),R.get(ⅰ).getSecondElm()));
    否则如果((R.get(ⅰ).getSecondElm()== p.getFirstElm())及&放大器;!(R.get(ⅰ).getFirstElm()= R.get(ⅰ).getSecondElm()) )
        R.add(新对(R.get(ⅰ).getFirstElm(),p.getSecondElm()));
    //其他
    //有在R没有对传递
}

使用foreach循环时,我得到的错误是:

 异常线程mainjava.util.ConcurrentModificationException
    在java.util.AbstractList中的$ Itr.checkForComodification(来源不明)
    在java.util.AbstractList中的$ Itr.next(来源不明)
    在set.problem.fourth.PoSet.makeTransitive(PoSet.java:145)
    在set.problem.fourth.PoSet.addToR(PoSet.java:87)
    在set.problem.fourth.PoSetDriver.typicalTesting(PoSetDriver.java:35)
    在set.problem.fourth.PoSetDriver.main(PoSetDriver.java:13)


解决方案

  

Java集合类是快速失败的,这意味着,如果
  而一些线程遍历了它集合将被改变
  使用迭代器,在 iterator.next()将抛出一个 ConcurrentModificationException的


  
  

这情况可以来在多线程的情况下,以及单
  线程环境。 - www.java codegeeks.com


您不能修改列表为/每个循环,这大约是语法糖的的Iterator 作为实现细节。您只能安全地调用一个.remove()直接使用迭代时


  

注意Iterator.remove是修改集合​​的唯一安全的方法
  在迭代;该行为是不确定的,如果基础
  集合被以任何其他方式修改,而迭代的
  进展。 - Java集合
  教程


调用。新增()为/每个循环修改的内容,而<$ C $内C>的Iterator 是在后台使用认为这并抛出这个异常。

一个更微妙的值得关注的是,你列出的第二种方式,在 .size()正在增加每次。新增(),所以你最终会处理所有的事情,你。新增(),这可能会造成死循环取决于输入数据是什么。我不知道,如果这是你的愿望。

解决方案

我会后创建另一个的ArrayList 。新增()将其所有的新东西,然后循环使用 .addAll()原始的ArrayList 将两个清单合并在一起。这将使事情你正在尝试做明确的,那就是除非你的意图是过程中的所有新加入的东西,你添加它们。

2014年解决方案:

总是使用永恒集合类和构建,而不是试图修改一个共享的一种新的永恒集合类。这基本上就是我2012回答说,但我想让它更加明确。

番石榴支持这个非常好,使用 ImmutableList.copyOf()来绕过数据。

使用 Iterables.filter()来的东西过滤掉进入一个新的 ImmutableList ,没有共享的可变状态,手段没有并发的问题!

I'm trying to make use of the foreach loop with the arraylist, but when I use it, it gives me error, but when I use normal for loop, it works perfectly, what could be the problem?

The code is here:

for (Pair p2 : R) {
    if ((p2.getFirstElm() == p.getSecondElm()) && (p2.getFirstElm() != p2.getSecondElm())) 
        R.add(new Pair (p.getFirstElm(), p2.getSecondElm()));
    else if ((p2.getSecondElm() == p.getFirstElm()) && (p2.getFirstElm() != p2.getSecondElm())) 
        R.add(new Pair (p2.getFirstElm(), p.getSecondElm()));

    // else
    // There are no transitive pairs in R.
}

this is the loop that doesnt work, and here is the one that works:

for (int i = 0; i < R.size(); i++) {
    if ((R.get(i).getFirstElm() == p.getSecondElm()) && (R.get(i).getFirstElm() != R.get(i).getSecondElm())) 
        R.add(new Pair (p.getFirstElm(), R.get(i).getSecondElm()));
    else if ((R.get(i).getSecondElm() == p.getFirstElm()) && (R.get(i).getFirstElm() != R.get(i).getSecondElm())) 
        R.add(new Pair (R.get(i).getFirstElm(), p.getSecondElm()));
    //else
    //  There are no transitive pairs in R.
}

the error I'm getting when using the foreach loop is:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
    at java.util.AbstractList$Itr.next(Unknown Source)  
    at set.problem.fourth.PoSet.makeTransitive(PoSet.java:145)  
    at set.problem.fourth.PoSet.addToR(PoSet.java:87)
    at set.problem.fourth.PoSetDriver.typicalTesting(PoSetDriver.java:35)
    at set.problem.fourth.PoSetDriver.main(PoSetDriver.java:13)

解决方案

Java Collection classes are fail-fast which means that if the Collection will be changed while some thread is traversing over it using iterator, the iterator.next() will throw a ConcurrentModificationException.

This situation can come in case of multithreaded as well as single threaded environment. - www.javacodegeeks.com

You can't modify a List in a for/each loop, which is syntactic sugar around the Iterator as an implementation detail. You can only safely call .remove() when using the Iterator directly.

Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress. - Java Collections Tutorial

Calling .add() inside the for/each loop modifies the contents, and the Iterator that is used behind the scenes sees this and throws this exception.

A more subtle concern is the that the second way you list, the .size() is increasing every time you .add() so you will end up processing all the things you .add(), this could possibly cause an endless loop depending on what the input data is. I am not sure if this is what you desire.

Solution

I would create another ArrayList and .add() to it all the new things, and then after the loop, use .addAll() on the original ArrayList to combine the two lists together. This will make things explicit in what you are trying to do, that is unless your intention is process all the newly added things as you add them.

2014 Solution:

Always use Immutable collections classes and build new Immutable collection classes instead of trying to modify a single shared one. This is basically what my 2012 answer says but I wanted to make it more explicit.

Guava supports this very well, use ImmutableList.copyOf() to pass around data.

Use Iterables.filter() to filter out stuff into a new ImmutableList, no shared mutable state, means no concurrency problems!

这篇关于在ArrayList的foreach循环里面添加时ConcurrentModificationException的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆