CopyOnWriteArrayList solves nothing in this case. Just using a (single) ArrayList is sufficient in this case. CopyOnWriteArrayList will always copy all objects in the list on each write, while ArrayList only needs to compact its array by shifting elements to fill the gap of the removed object, which on average is half the objects. In addition it generates a significant amount of garbage due to the arrays being created. From a performance view CopyOnWriteArrayList is worse in all cases. However, for something as simple as a few items that aren’t even being updated each frame any performance wins are insignificant, so this whole argument is meaningless.
My interpretation of the original post was that he was talking about his game entities, e.g. objects that are updated each frame. In that case we already have a loop over the objects in place. This is a perfect fit for a double buffered ArrayList, since the additional overhead per frame will be very low.
Original code using only one ArrayList:
ArrayList<Entity> entities = ...;
for(int i = 0; i < entities.size(); i++){
Entity e = entities.get(i);
e.update();
if(!e.isAlive()){
entities.remove(i--);
}
}
Double buffered ArrayList:
ArrayList<Entity> entities1 = ...;
ArrayList<Entity> entities2 = ...;
for(int i = 0; i < entities1.size(); i++){
Entity e = entities1.get(i);
e.update();
if(e.isAlive()){
entities2.add(e);
}
}
entities1.clear();
ArrayList<Entity> temp = entities1;
entites1 = entities2;
entities2 = temp;
This has several performance advantages. The biggest performance related win isn’t peak performance since adding the objects to a second list isn’t free (although it is cheap). The win here lies in predictable performance. Often you’ll get to a point where many objects die simultaneously. Maybe there was an explosion, maybe all the pellets fired from a shotgun hit a wall at almost the same time, maybe a parent object died so all child objects automatically died as well, etc etc etc. In addition, such events generally are slow to compute in the first place (expensive collision detection, having to update all child objects, etc), so we already have a smaller time budget than usual. Let’s say that we use the single ArrayList approach and we have 1000 objects and 100 die within a single frame, the average list size will be 950 and we need to on average move half those objects each update. That’s 47 500 moves in a single frame. A CopyOnWriteArrayList would in this case have to copy all objects, not just the following ones, so we’d be copying the full 95 000 object in a single frame. The result is a horrible performance spike where we’re potentially freezing up the game for several milliseconds for no good reason. Using a double buffered ArrayList we only suffer a small predictable performance hit to be able to get rid of all remove()s for that list, elimination copy “bursts” consisting of tens of thousands of copies for a static 1 000 copies per frame.
What exactly is CopyOnWriteArrayList supposed to solve here? It’s only advantage over a normal ArrayList is that it’s thread safe. Nowhere does OP say that he’s using multiple threads. ConcurrentModificationExceptions are generally caused by people removing stuff from within a for-each loop which have a hidden Iterator object.