Почему нет ошибок при использовании iterator.remove?
Если я использую Iterator.remove()
, Все отлично. Если я использую ArryaList.remove()
Я всегда получаю ошибку java.util.ConcurrentModificationException
,
Кто-нибудь может указать причину?
4 ответа
В основном потому, что так оно и работает. Если вы удаляете элемент из списка, итератор об этом не знает, а когда он пытается получить доступ к другому элементу в списке, список изменяется и возникает ошибка. Но если вы удаляете элемент через итератор, то итертор знает об удалении, вносит соответствующие изменения в свои структуры данных и продолжает работу.
Javadocs говорят все это:
Это исключение может быть вызвано методами, которые обнаружили одновременную модификацию объекта, когда такая модификация недопустима.
Например, как правило, один поток не может изменять коллекцию, пока другой поток выполняет итерацию по ней. В общем, результаты итерации в этих обстоятельствах не определены. Некоторые реализации Iterator (включая реализации всех реализаций коллекций общего назначения, предоставляемых JRE) могут выбрасывать это исключение, если обнаруживается такое поведение. Итераторы, которые делают это, известны как итераторы с быстрым отказом, так как они быстро и чисто терпят неудачу, а не рискуют произвольным, недетерминированным поведением в неопределенное время в будущем.
Вы изменяете коллекцию и выполняете ее одновременно.
Так именно из документов
Это исключение может быть вызвано методами, которые обнаружили одновременную модификацию объекта, когда такая модификация недопустима.
Например, как правило, один поток не может изменять коллекцию, пока другой поток выполняет итерацию по ней. В общем, результаты итерации в этих обстоятельствах не определены. Некоторые реализации Iterator (включая реализации всех реализаций коллекций общего назначения, предоставляемых JRE) могут выбрасывать это исключение, если обнаруживается такое поведение. Итераторы, которые делают это, известны как итераторы с быстрым отказом, так как они быстро и чисто терпят неудачу, а не рискуют произвольным, недетерминированным поведением в неопределенное время в будущем.
Посмотрите на Class ConcurrentModificationException
Если вам нужно удалить элемент во время итерации по списку, вы всегда должны использовать итератор.
например
List<String> list = //...
//...
Iterator<String> iter = list.iterator();
while(iter.hasNext()) {
String str = itr.next();
//...
if(/* ... */) {
iter.remove(str);
}
}
Это самый безопасный способ удаления элемента из списка, пока вы выполняете итерацию по списку.
Примечание: вы не должны делать что-то следующее:
List<String> list = //...
//...
for(String str : list) {
if(/* ... */) {
list.remove(); // <-- should not do this
}
}
Где в основном вы окажетесь в ConcurrentModificationException
, В расширенном цикле for используется итератор. И вы вручную удаляете элемент из списка вместо того, чтобы проходить через итератор. Вот почему вы получаете это исключение.