Почему один цикл генерирует исключение ConcurrentModificationException, а другой нет?

Я столкнулся с этим, когда писал программу коммивояжера. Для внутреннего цикла я попробовал

for(Point x:ArrayList<Point>) {
// modify the iterator
}

но при добавлении еще одной точки в этот список выбрасывалось ConcurrentModicationException.

Однако, когда я изменил цикл на

for(int x=0; x<ArrayList<Point>.size(); x++) {
// modify the array
}

цикл работал нормально, не вызывая исключения.

Оба цикла for, так почему же один генерирует исключение, а другой нет?


person Jason    schedule 07.03.2010    source источник
comment
возможный дубликат цикла в списке с удалением   -  person McDowell    schedule 09.05.2011


Ответы (5)


Как объяснили другие, итератор обнаруживает изменения в базовой коллекции, и это хорошо, поскольку может привести к неожиданному поведению.

Представьте себе этот код без итераторов, который изменяет коллекцию:

for (int x = 0; list.size(); x++)
{
  obj = list.get(x);
  if (obj.isExpired())
  {
    list.remove(obj);
    // Oops! list.get(x) now points to some other object so if I 
    // increase x again before checking that object I will have 
    // skipped one item in the list
  }
}
person Martin    schedule 07.03.2010
comment
Я выбрал ваш ответ, потому что вы показали, как что-то может пойти не так при повторении по сравнению с доступом через get() - person Jason; 07.03.2010

В первом примере используется итератор, во втором нет. Это итератор, который проверяет одновременную модификацию.

person Jim Blackler    schedule 07.03.2010

первый код использует итератор, поэтому изменение коллекции не допускается. Во втором коде вы получаете доступ к каждому объекту с помощью x.get(i), поэтому не используете итератор, поэтому разрешены модификации.

person Persimmonium    schedule 07.03.2010

Вы не можете изменить List, пока перебираете его, что вы делаете в первом примере. Во втором у вас просто обычный цикл for.

person fastcodejava    schedule 07.03.2010

Если вы запустите код и обнаружите, что первая итерация цикла работает нормально, но вторая выдает ConcurrentModicationException

если это потому, что метод next() проверяет, не изменилось ли количество элементов.

Хорошее объяснение см. на странице http://javaadami.blogspot.com/2007/09/enhanced-for-loop-and.html

person Damian    schedule 26.04.2014