I got the same problem recently and I fix it by making a copy of my ArrayList.

But I have a question regarding the synchronization.

I was accessing my ArrayList with a method getList() and I was clearing the list with clearList() in the same class as getList(). I was also iterating through the list I got from getList() and that cause problem when clearList() was call at the same time.

If I had synchronize both getList() and clearList() would it have fix my problem? Or getList() just return a pointer to my ArrayList then the method terminate.

You can create an empty ArrayList (called removeList) before you start iterating that collection. Once you see a item you want to remove, you add it to the removeList. Once you're done, you can iterate the removeList and remove those items from the collection.

Here's an example of what I'm using to update a set of entities, and remove dead entities (like killed units, expired bullets):

You can create an empty ArrayList (called removeList) before you start iterating that collection. Once you see a item you want to remove, you add it to the removeList. Once you're done, you can iterate the removeList and remove those items from the collection.

Unfortunately, that will become extremely slow when your lists get bigger. Every item you remove, will have to be searched throughout the whole list, and on average located in the center of the list. Every remove will also be very slow in an ArrayList (it has to shift all references after the index, to the left - a LinkedList is much faster, but slower to build).

When you're removing lots of items, or removing few items on a large list, it will become a serious performance bottleneck.

The alternative it so copy everything into a list that you keep, as apposed to remove. Adding to an ArrayList is very fast, and you never have to remove an item.

1 2 3 4 5 6 7 8 9 10 11 12 13

Listitems = newArrayList();Listretain = newArrayList();

for(Objectitem: items){if(needed(item)) {retain.add(item); }}

items.clear();items.addAll(retain);

Hi, appreciate more people! Σ ♥ = ¾Learn how to award medals... and work your way up the social rankings!

Unfortunately, that will become extremely slow when your lists get bigger. Every item you remove, will have to be searched throughout the whole list, and on average located in the center of the list. Every remove will also be very slow in an ArrayList (it has to shift all references after the index, to the left - a LinkedList is much faster, but slower to build).

When you're removing lots of items, or removing few items on a large list, it will become a serious performance bottleneck.

The alternative it so copy everything into a list that you keep, as apposed to remove. Adding to an ArrayList is very fast, and you never have to remove an item.

1 2 3 4 5 6 7 8 9 10 11 12 13

Listitems = newArrayList();Listretain = newArrayList();

for(Objectitem: items){if(needed(item)) {retain.add(item); }}

items.clear();items.addAll(retain);

Doesn't seem to be any performance bottleneck in my game using ArrayList in my games, I have hundreds of bullets flying around and expiring every few seconds. I'll take a look at the LinkedList idea though, seems like a logical choice of data structure!

However...I don't agree with your code example. This requires creating a new ArrayList every time there is an update() call. So, for a game running at 100 FPS this means creating 100 ArrayList's every 1 second. I can just see the garbage collector going into overdrive and hogging the system.

ArrayList.addAll(): Appends all of the elements in the specified Collection to the end of this listArrayList.clear(): Iterates all items in the collection and sets them to null.

Worst case scenario you're iterating the list THREE TIMES if you're retaining all the items, which is mostly the case in every game loop.

By modifying my idea to use LinkedList you'll get O(2*n) (removing all objects which is never the case), but in your idea is O(3*n) (when keeping all objects which is almost always the case)

Unfortunately, that will become extremely slow when your lists get bigger. Every item you remove, will have to be searched throughout the whole list, and on average located in the center of the list. Every remove will also be very slow in an ArrayList (it has to shift all references after the index, to the left - a LinkedList is much faster, but slower to build).

When you're removing lots of items, or removing few items on a large list, it will become a serious performance bottleneck.

The alternative it so copy everything into a list that you keep, as apposed to remove. Adding to an ArrayList is very fast, and you never have to remove an item.

1 2 3 4 5 6 7 8 9 10 11 12 13

Listitems = newArrayList();Listretain = newArrayList();

for(Objectitem: items){if(needed(item)) {retain.add(item); }}

items.clear();items.addAll(retain);

That was what I used to do, and it created 1 linkedlist every 20 millseconds therefore lagging the game out.

However...I don't agree with your code example. This requires creating a new ArrayList every time there is an update() call. So, for a game running at 100 FPS this means creating 100 ArrayList's every 1 second. I can just see the garbage collector going into overdrive and hogging the system.

First, if you're worried about GC, you can always hang on to the old ArrayList and clear it instead of making a new one.

But there's no point: 100 ArrayLists every second is never ever ever EVER going to bottleneck your program if you're running on the desktop, unless you're either writing literally the most tightly optimized code I've ever seen in my life or working with some fantastically large lists.

I ran a quick test, doing a manual filtered ArrayList copy (pretty much exactly as Riven suggested): I started with a 1000 element ArrayList<Float> filled with random values between 0 and 1; for each iteration I created a new ArrayList (pre-allocated to the size of the old one so I don't waste time growing it), and copied elements over unless their values were less than 0.1, in which case I randomly generated new ones. After each iteration I copied the old list into the new one after a clear.

Clearly there's a lot of inefficient stuff in there, the random calls and the autoboxing; I know this, the point is, you should at least be able to achieve this performance.

I got 17,500 iterations per second on my Macbook Pro using the client JVM. A small GC happened about every 100 iterations, usually taking about .0002 seconds (garbage came from autoboxing).

I tried the same test actually creating new ArrayLists each time, and got very similar results, FWIW.

100 vs. 17,500: That's not even worth thinking about, let alone optimizing for, unless you're working on a platform that can't handle any amount of GC (Android or J2ME, for instance), in which case you're designing from day one to work around issues like this.

Also, just so we're being complete, if you really want to alter an ArrayList while you're iterating over it and don't want to deal with iterators, it's easy:

However, as Riven mentioned, remove calls on ArrayLists are expensive, since they arraycopy the whole tail of the array, and further, floats.size() is not constant so it must be evaluated every time you loop. I'm pretty sure the JVM can optimize away most of those tests as well as most of the bounds checks if you don't alter the list while iterating.

Read up on the 3 things you have to care about with concurrent/parallel programming: Ordering Visibility and Atomicity - Don't go decorating your whole code with synchronised or some other random language construct.

As for handling removals just leave it to the implementation. If you want to aggregate the removal to reap some performance gains then I guess so - but I'd advice first building a game that actually needs it. Use ravens first suggestion until.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org