Удаление элемента в for-each — не всегда ConcurrentModificationException
Классический ответ на вопрос «что будет, если удалить элемент из List во время итерации» — «выбросится ConcurrentModificationException». Это верно не во всех случаях, и именно эта неточность ловит на собеседовании.
ArrayList.Itr проверяет modCount в next() и hasNext() по-разному: hasNext() сравнивает cursor и size, next() сверяет modCount. Если удаляемый элемент — предпоследний в списке, после remove() size уменьшается, cursor становится равным size, hasNext() возвращает false, и цикл завершается без вызова next() — а значит без проверки modCount и без исключения.
List names = new ArrayList<>( List.of("a", "b", "c"));
for (String name : names) { if (name.equals("b")) { names.remove(name); } }
В этом примере "c" останется необработанным без единой ошибки в логе — цикл просто завершится на два элемента раньше, чем ожидалось. Правильный вариант — Iterator.remove() внутри while(iterator.hasNext()) или List.removeIf(), который делает то же самое безопасно.
Отсутствие исключения — не признак того, что код работает правильно.
Тренажёр: 600 вопросов, мок с таймером, план повторов
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки