迭代Arraylist时的ConcurrentModificationException(不删除)

时间:2013-03-13 20:23:05

标签: java android exception concurrency

我目前在迭代ArrayList时遇到问题。我在这里看过几篇文章,但似乎没有解决我的问题。这是我的代码:

//restaurants contains a list of all restaurants and i want to filter them
List<Restaurant> newList = new ArrayList<Restaurant>();
List<Restaurant> allRestaurants = new ArrayList<Restaurant>(restaurants);
if (query != null && query.length() > 0 && !query.equals("*")) {
            synchronized (allRestaurants) {
                for (Iterator<Restaurant> it = allRestaurants.iterator(); it
                        .hasNext();) {
                    Restaurant restaurant = it.next();
                    if (restaurant.getCity().contains(query)) {
                        synchronized (newList) {
                            newList.add(restaurant);
                        }
                    } else {
                        newList = allRestaurants;
                    }
                }
            }

这是代码被我修改了,我已经在这里阅读了几个想法(同步,使用迭代器而不是for-each-loop)。我甚至已经同步了整个方法,但仍然有例外。

例外发生在以下行:

Restaurant restaurant = it.next();

我不明白。我没有操纵这一行中的列表。为什么会发生这种情况?我该如何解决?

5 个答案:

答案 0 :(得分:4)

else{
    newList = allRestaurants;
}

这几乎可以肯定是你的问题。

newList分配给allRestaurants,然后添加到newList会导致您的编纂。

newList = allRestaurants之后,newList的任何添加都会更新allRestaurants中的mod计数,从而更新错误。

答案 1 :(得分:0)

在else分支

else {
   newList = allRestaurants;
}

您将newList设为allRestaurants。下一个修改newList.add(restaurant);会更改allRestaurants列表。

调用it.next()时会抛出异常,因为迭代器会检查其源是否已更改。

答案 2 :(得分:0)

失败始于:

newList = allRestaurants;

指向同一列表的两个引用(即您正在迭代的列表)。然后,您执行以下操作:

newList.add(restaurant);

修改列表。来自ConcurrentModificationException的javadoc:

  

请注意,此异常并不总是表示某个对象已被另一个线程同时修改。如果单个线程发出违反对象合同的一系列方法调用,则该对象可能会抛出此异常。例如,如果线程在使用失败快速迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。

答案 3 :(得分:0)

您的问题出在else子句中。

         newList = allRestaurants;

这就是你获得例外的原因

答案 4 :(得分:0)

您无法更改循环内用于迭代的ArrayList;这就是ConcurrentModificationException所说的(http://docs.oracle.com/javase/1.4.2/docs/api/java/util/ConcurrentModificationException.html)和newList = allRestaurants;以及newList.add(restaurant);可能会更改列表allRestaurants

所以你能做的就是

  1. 创建另一个列表
  2. 将要修改的项目放在该列表中
  3. 在循环后
  4. 添加/删除新列表(addAllremoveAll)到您的旧列表

    查看http://www.javacodegeeks.com/2011/05/avoid-concurrentmodificationexception.html了解更多信息。