3

我目前在遍历 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();

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

4

5 回答 5

3
else{
    newList = allRestaurants;
}

这几乎肯定是你的问题。

分配newListallRestaurants然后添加到newList会导致您的共修改。

那是在newList = allRestaurants任何添加newList将更新mod计数allRestaurants并因此更新您的错误之后。

于 2013-03-13T20:27:00.337 回答
0

在 else 分支

else {
   newList = allRestaurants;
}

你设置newListallRestaurants. 下一个修改newList.add(restaurant);更改了 allRestaurants-list。

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

于 2013-03-13T20:28:39.460 回答
0

失败始于:

newList = allRestaurants;

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

newList.add(restaurant);

修改列表。来自的javadoc ConcurrentModificationException

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

于 2013-03-13T20:29:23.467 回答
0

您的问题出在 else 子句中。

         newList = allRestaurants;

这就是为什么你会得到例外

于 2013-03-13T20:29:27.043 回答
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. 循环后将addAll新列表(或removeAll)添加/删除到旧列表

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

于 2013-03-13T20:33:03.067 回答