Как избежать «ConcurrentModificationException» при добавлении элементов ArrayList?

Я пытаюсь добавить элемент в ArrayList в определенном порядке

Iterator<Rating> it = arr.iterator();
while(it.hasNext()){
    Rating o = it.next();
    int index = arr.indexOf(o);
    if (o.getRating() < this.getRating()) {
        arr.add(index, this);
    }
}

Я получаю ConcurrentModificationException при попытке сделать это. Есть ли какое-то простое решение для решения этой проблемы?

Если вы можете получить listIterator(), вызвав add на итераторе. В противном случае: найти индекс, добавить элемент после итерации

knittl 06.05.2022 21:17
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
38
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Возможно, вместо ArrayList подойдет одна из следующих коллекций?

КопиОнВритеАррайлист позволит вам писать, не вызывая ConcurrentModificationException. Является ли это хорошим выбором или нет, зависит от относительной частоты операций записи в итерациях.

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

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

knittl 07.05.2022 12:27

@knittl Вы имели в виду должен быть изменен из того же итератора? ConcurrentModificationException возникает, если коллекция изменяется вне итератора. Если модифицировать через итератор, то работает нормально.

Mark Rotteveel 07.05.2022 13:50

@MarkRotteveel извините, я не ясно выразился. Вы не должны изменять коллекцию с помощью методов коллекции. Вызов методов на итераторе в порядке (как вы указали, спасибо!). Изменение их из другого потока допустимо для параллельных коллекций. Чего не следует делать, так это (упрощенно): var iterator = coll.iterator(); while (iterator.hasNext()) { coll.remove(iterator.next()); } (или добавлять, устанавливать и т.д.) Вы не получите исключения, но оно почти наверняка намекает на недочет в вашей программе или на непонимание того, как работают коллекции (помимо очевидного O (n²) поведение в моем примере).

knittl 07.05.2022 15:13

Другие вопросы по теме