Я работаю над игрой, в которой каждый раз, когда пользователь касается экрана, в список добавляется пуля. И периодически я просматриваю этот список, чтобы что-то сделать.

Чтобы избежать исключения ConcurrentModificationException, я сначала сделал копию списка, а затем перебрал его.

List<Bullet> temp = bullets; // main list is bullets
for (Bullet b : temp) {
  // do something
}

Но это все равно иногда приводило к возникновению исключения ConcurrentModificationexception. Но когда я скопировал массив с помощью CopyOnWriteArrayList, этого не произошло.

CopyOnWriteArrayList<Bullet> temp1 = new CopyOnWriteArrayList<Bullet>(bullets);

Почему это работает вместо этого? Информация, которую я нашел в Интернете, говорит об изменении списка непосредственно во время его повторения, но я уже делал копию списка раньше. Так почему же копирование списка через ArrayList не работает, а копирование через CopyOnWriteArrayList работает?

0
Saurav 10 Янв 2022 в 18:34
1
См. ответ от языка поло ниже. Однако, даже если вы сделаете копию и повторите ее, вы все равно можете получить ту же ошибку, потому что список может быть изменен во время создания копии. Это просто менее вероятно, поскольку копия создается очень быстро.
 – 
ewramner
10 Янв 2022 в 18:42
Это потому, что для копирования списка Java сначала выполняет итерацию по нему? Или есть какая-то другая причина?
 – 
Saurav
10 Янв 2022 в 19:06

1 ответ

Лучший ответ

temp не является копией списка bullets, это копия ссылки на bullets. Таким образом, temp и bullets указывают на один и тот же List, и, следовательно, любая модификация, сделанная по одной ссылке, видна по другой ссылке. Что вам действительно нужно, так это новый List, который содержит те же элементы, что и оригинал. Один из способов сделать поверхностную копию List — использовать конструктор копирования для ArrayList следующим образом:

List<Bullet> temp = new ArrayList<>(bullets);

Это копирует каждую ссылку Bullet из bullets в новую List, которая затем не зависит от оригинала. Это как раз то, что вы делаете с CopyOnWriteArrayList, что (одна из причин) более устойчиво к одновременным изменениям.

2
polo-language 10 Янв 2022 в 18:39
В этом есть смысл, спасибо!
 – 
Saurav
10 Янв 2022 в 19:03