Почему этот код не бросает ConcurrentModificationException
? Он изменяет Collection
во время итерации через него, не используя метод Iterator.remove()
, который должен быть единственным безопасным способом удаления.
List<String> strings = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String string : strings)
if ("B".equals(string))
strings.remove("B");
System.out.println(strings);
Я получаю тот же результат, если заменить ArrayList
на LinkedList
. Однако, если я изменил список на ("A", "B", "C", "D)
или просто ("A", "B")
, я получаю исключение, как ожидалось. Что происходит? Я использую jdk1.8.0_25
, если это имеет значение.
EDIT
Я нашел следующую ссылку
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4902078
Соответствующий раздел
Наивное решение состоит в том, чтобы добавить проверки на comodification в hasNext в AbstractList, но это удваивает стоимость проверки кодофикации. Оказывается, достаточно выполнить тест только на последнем итерации, что практически ничего не добавляет к стоимости. Другими словами, текущая реализация hasNext:
public boolean hasNext() { return nextIndex() < size; }
Заменяется этой реализацией:
public boolean hasNext() { if (cursor != size()) return true; checkForComodification(); return false; }
Это изменение не будет сделано, потому что внутренний регулирующий орган ВС отклонил его. Официальное постановление указало, что изменение "имеет продемонстрировали потенциал значительного воздействия на совместимость по существующему коду". ( "Эффект совместимости" заключается в том, что исправление имеет возможность заменить молчаливое неправильное поведение ConcurrentModificationException.)