2013-03-13 8 views
3

У меня в настоящее время есть проблема с итерацией через ArrayList. Я прочитал несколько сообщений здесь, но ничто, похоже, не разрешило мою проблему. Вот мой код:ConcurrentModificationException при повторении через 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; 
        } 
       } 
      } 

Это код был изменен мной с несколькими идеями я читал здесь (синхронизированных с использованием итератора вместо для-каждой петли). Я даже синхронизировал весь метод и все еще получаю исключение.

Исключение происходит в следующей строке:

Restaurant restaurant = it.next(); 

, которые я не понимаю. Я не манипулирую списком в этой строке. Почему это происходит и как я могу это исправить?

+0

Вы, вероятно, не хотите иметь вложенный синхронизированный блок –

ответ

4
else{ 
    newList = allRestaurants; 
} 

Это почти наверняка ваша проблема.

Назначение: newList - allRestaurants, после чего добавление в newList вызывает вашу комодификацию.

То есть после newList = allRestaurants любое добавление newList обновит число мод в allRestaurants и, соответственно, на вашу ошибку.

+0

, вы правы .. я также нашел его там. он должен принадлежать внешнему if-case – MrHill

0

В остальное ветви

else { 
    newList = allRestaurants; 
} 

Вы устанавливаете newList быть allRestaurants. Следующая модификация newList.add(restaurant); изменяет список allRestaurants-list.

Исключение выбрано, когда вызывается it.next(), потому что тогда итератор проверяет, был ли его источник изменен.

0

Провал начинается с:

newList = allRestaurants; 

, который указывает как ссылки на тот же список (то есть тот, который вы итерация). Затем вы делаете следующее:

newList.add(restaurant); 

изменение списка. Из Javadoc из ConcurrentModificationException:

Заметим, что это исключение не всегда означает, что объект был изменен одновременно другим потоком. Если один поток выдает последовательность вызовов методов, которые нарушают договор объекта, объект может выдать это исключение. Например, если поток изменяет коллекцию напрямую, когда он выполняет итерацию по коллекции с быстрым итератором, итератор выкинет это исключение.

0

Ваша проблема в предложении else.

  newList = allRestaurants; 

Вот почему вы получите исключения

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 для получения дополнительной информации.

 Смежные вопросы

  • Нет связанных вопросов^_^