Why does an Arraylist throw ConcurrentModificationexception even when a copy is made, but CopyOnWriteArrayList doesn't?



I’m working on a game where every time the user touches the screen, a bullet gets added to the list. And periodically, I am iterating over that list to do something.

To avoid ConcurrentModificationexception, I made a copy of the list first and then iterated over it.

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

But this still ended up throwing a ConcurrentModificationexception some of the time. But when I copied the array with CopyOnWriteArrayList, this didn’t happen.

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

Why does this work instead? The information I found online talks about modifying a list directly while iterating over it, but I was already making a copy of the list before. So why does making a copy of the list through ArrayList not work, but making a copy through CopyOnWriteArrayList does?


temp is not a copy of the list bullets, it is a copy of the reference to bullets. So temp and bullets point to the same List and hence, any modification made through one reference is visible via the other reference. What you really need is a new List that contains the same elements as the original. One way to make a shallow List copy is to use the copy constructor for ArrayList like so:

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

This copies each Bullet reference from bullets into a new List, which is then independent of the original.
That’s just what you’re doing with the CopyOnWriteArrayList, which is (one of the reasons) it is more resilient to concurrent modification.

Answered By – polo-language

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave A Reply

Your email address will not be published.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More