Подтвердить что ты не робот

Как изменить коллекцию при повторении с использованием for-each цикла без ConcurrentModificationException?

Если я изменяю коллекцию, итерации по ней, используя цикл for-each, она дает ConcurrentModificationException. Есть ли способ обхода?

4b9b3361

Ответ 1

Используйте Iterator#remove.

Это единственный безопасный способ изменения коллекции во время итерации. Для получения дополнительной информации см. Учебник по интерфейсу коллекции.

Если вам нужна возможность добавлять элементы во время итерации, используйте ListIterator.

Ответ 2

Одна работа заключается в том, чтобы сохранить изменения и добавить/удалить их после цикла.

Например:

List<Item> toRemove = new LinkedList<Item>();

for(Item it:items){
    if(remove){
        toRemove.add(it);
    }
}
items.removeAll(toRemove);

Ответ 3

Вторым обходным решением является использование класса коллекции, итераторы которого не будут давать исключение. Например ConcurrentLinkedQueue, ConcurrentHashMap и т.д..

Они избегают необходимости исключать исключения, предоставляя более слабые модели согласованности для итераторов. (Конечно, вам нужно понять эти модели и решить, подходят ли они для вашего приложения.)

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

Ответ 4

Если вы просто хотите удалить элемент из коллекции, вы можете использовать Iterator вместо Iterable.

В противном случае вы можете не перебирать исходную коллекцию, а сначала сделать копию списка. Например, если ваша коллекция является списком, вы можете создать новый ArrayList (originaList) и перебрать его. Изменения должны быть внесены в исходный список.

Другая альтернатива, которая может быть лучше для вашего случая использования, не должна использоваться для каждого, но традиционная для -.