Saurav
Saurav

Reputation: 45

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?

Upvotes: 0

Views: 138

Answers (2)

Mohan k
Mohan k

Reputation: 68

Both ArrayList and CopyOnWriteArrayList implements the Iterable,

The ArrayList implemetation of Iterable, next() method maintains modcount/cursor with size internal array, so change on the original list will throw ConcurrentModificationException and also ArrayList support remove() of Iterable because it is safely modifies the cursor.

CopyOnWriteArrayList implemetation of Iterable, next() method only reads internal array elements and even not support remove() of Iterable.

Upvotes: 0

polo-language
polo-language

Reputation: 846

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.

Upvotes: 2

Related Questions