Best way to iterate through ArrayList?

I know four ways to do this… But which way is the best?

  1. Using an iterator
  2. Using a for loop with array.size() as the max value
  3. Using array.toArray(new [0]);
  4. Just using for ( val : array) {} (this actually works!)

Just as a note, I will be iterating through it a lot so what is actually the best way which is easiest and the best?

“Which way is best?”

:expressionless:

Raw performance: c-style for loop, only really matters if it’s an inner loop as it saves creating an iterator each time
List.toArray() makes a copy each time, horrible
Enhanced for: syntax sugar for creating an iterator, use in most cases. The sugar exists for a reason.
Manual Iterator: If you need to remove values while iterating, or need a ListIterator or some other specific iterator.
There’s also while loops, which are sometimes more readable. And the rare do-while loop.
Also rare: recursive method that traverses the list

EDIT: and streams!

Streams are probably my new favorite way of going through some Collection to perform operations on it. They’re like LINQ for Java! :slight_smile:

So use array.size()?
What about if I want to return an array from an ArrayList? Do I use array.toArray(new [0])?

Personally I use No.2, it’s just easy to code IMO.

But I’d love to hear of a faster way, as I use quite a lot of ArrayLists in Retro-Pixel Castles.

Here’s another. :wink:


try {
    array[idx++];
}
catch(ArrayIndexOutOfBoundsException e){}

Surely that is considered hacky? lol

@OP, I tend to use the enhanced for each loop. Easy to ready, fast to code and seems to do the job.


for(Foo foo : listOfFoos){
    foo.something();
}


Using an iterator or the enhanced for loop means a tiny extra loop-set-up cost (just a handful of variables in the iterator object) which is irrelevant if the loop’s going round more than a handful of times. Then each time round, it’ll be doing a couple of extra tests, which may be somewhat significant if the looped block’s got very little in it, like searching for an element then breaking out or something trivial like that.

In general I’d say use the one which reads best in the context of what the code’s doing at the time, usually the Java enhanced for loop if possible because it’s neatest, otherwise what BurntPizza said. Tune later if need be.

In particular I don’t like using a for (int x…) loop when x isn’t used for anything else except obtaining the next item. Apart from being less elegant it runs the risk of creating a problem later if the list is changed to a different type with inefficient random access.

(No-one ever uses any other kind of list than an ArrayList, mind :))

Cas :slight_smile:

What about modifying it a lot? Do you need to modify the list while iterating it?

Both those questions may impact on the right solution. In Praxis LIVE I have various ‘collections’ which are iterated often, modified rarely and occasionally modified while iterating. I’m actually using arrays and this simple class which handles adding or removing an item and returning a copy of the array. It’s basically externalising some of the functionality of CopyOnWriteArrayList. It has the added benefit of allowing to use the enhanced-for loop without creating an iterator.

The “best” way I think is this:


for (int i = projectiles.size() - 1; i >= 0; i--)
{
	projectiles.get(i); // do something
		
	if (removeCriteria)
	{
		projectiles.remove(i);
	}
}

I call it the reverse loop, and it allows you to iterate AND remove elements in the same loop.

Nah! Best quickest algorithm is this: :stuck_out_tongue:

for (int len = projectiles.size(), i = len; i-- != 0; )
  if (projectiles.get(i).removeCriteria()) {
    projectiles.set(i, projectiles.get(--len));
    projectiles.remove(len);
  }

Yep.

I just found a discussion of the technique:

[quote]try-catch blocks generally use no extra time if no exception is thrown…Throwing an exception and executing the catch block has a significant overhead. This overhead seems to be due mainly to the cost of getting a snapshot of the stack when the exception is created…Generally, the performance cost of throwing an exception is equivalent to several hundred lines of simple code executions…You can reduce the cost by reusing an exception object rather than creating a new one…is two orders of magnitude faster…the sole disadvantage of reusing an exception instance is that the instance does not have the correct stack trace…
[/quote]
From Java Performance Tuning by Jack Shirazi, 2003. (pages 172-176)

It definitely seems like asking for trouble. In chapter 7, Shirazi profiles examples of a few cases where it might eek out a slight performance benefit. The best case that can be made for its use is if the end test is a significant percentage of the looping code (i.e., only a couple statements in the loop) and the number of iterations is really large. Then, perhaps the gain in dropping the iteration-is-done test outweighs the cost (assuming you throw an existing exception rather than generating a new one). But you still have to deal with the inevitable WTF that occurs when looking at the code fresh a few months later.

[quote=“philfrei,post:13,topic:51491”]
It would be cool if you could install a custom exception type to be thrown instead of ArrayIndexOutOfBoundsException, and the custom type didn’t collect a stack trace.

(By cool I mean evil :D)

More info on that: http://java-performance.info/throwing-an-exception-in-java-is-very-slow/

About the loops: GoToLoop’s (heh) is better than Cero’s for ArrayList simply because it avoids large copies. I forgot to mention that technique in my initial post.

If order isn’t important to you! In fact, @Cero’s answer would also be problematic if order was important. I remember someone (think @princec) posting a technique in an old thread on this using two ArrayLists, and ping-ponging valid values between them, which avoids most large array copies and retains the ordering.

As I said in my answer above, there is not really a way to answer the OP’s question without context, and for that matter the question may be incorrect assuming ArrayList answers that problem in the first place. One rarely iterates ArrayLists just for the hell of it! :wink:

That thread ended up with an even simpler implementation using no extra space and very cache-friendly, and also has the ability to allow new things to be added to the list while it’s iterating:


for (int i = 0, pos = 0; i < list.size(); i ++) {
	Thing thing = list.get(i);
	thing.doStuff();
	if (thing.isActive()) {
		list.set(pos ++, thing);
	}
}
// This next bit could be implemented more efficiently probably if the list had some sort of truncation method
for (int i = list.size(); --i >= pos;) {
	list.remove(i);
}

Cas :slight_smile:

the bag by kappa : http://www.java-gaming.org/topics/the-bag-fast-object-collection/24203/view.html
RW collection by riven : http://www.java-gaming.org/topics/readwritecollection-for-entities/28660/view.html

use these, do not use ArrayList (if you ask for the “best” way), at least use http://fastutil.di.unimi.it/

make your own array-list class.

o/

Ah, nice, I’d forgotten or not read that bit! :slight_smile:

Subclassing ArrayList and using removeRange(…) might be slightly more efficient?

Thx for the responses… But if I had an ArrayList called enemies (for example)…
And I had a method called getEnemies which returns a normal array… What is the best way to convert it? At the moment I am using enemies.toArray(new Enemy[0]);
(Actually im not because I don’t have an array called enemies)