views:

3680

answers:

9

What, if any, is the performance difference between the following two loops?

for(Object o: objectArrayList){
    o.DoSomthing();
}

and

for(int i=0; i<objectArrayList.size(); i++){
    objectArrayList.get(i).DoSomthing();
}
+37  A: 

From Item 46 in Effective Java by Joshua Bloch :

The for-each loop, introduced in release 1.5, gets rid of the clutter and the opportunity for error by hiding the iterator or index variable completely. The resulting idiom applies equally to collections and arrays:

// The preferred idiom for iterating over collections and arrays
for (Element e : elements) {
    doSomething(e);
}

When you see the colon (:), read it as “in.” Thus, the loop above reads as “for each element e in elements.” Note that there is no performance penalty for using the for-each loop, even for arrays. In fact, it may offer a slight performance advantage over an ordinary for loop in some circumstances, as it computes the limit of the array index only once. While you can do this by hand (Item 45), programmers don’t always do so.

Vijay Dev
Worth mentioning that in a for-each loop there is no way to access an index counter (since it doesn't exist)
basszero
+4  A: 

No, there's no performance penalty. The for each loop in Java is implemented entirely in the compiler. The compiler converts the for each loop to to an indexed loop, so the JVM doesn't see a difference.

There is a difference in that you can't modify the list if you use the for each loop. It uses an Iterator behind the scenes, and directly modifying the list will cause a ConcurrentModificationException to be thrown.

Bill the Lizard
A: 

Even with something like an ArrayList or Vector, where "get" is a simple array lookup, the second loop still has additional overhead that the first one doesn't. I would expect it to be a tiny bit slower than the first.

Paul Tomblin
The first loop has to get each element too. It creates an iterator behind the scenes to do this. They're really equivalent.
Bill the Lizard
Thinking in terms of C, an iterator can just increment a pointer, but a get would have to multiply the value of i by the width of a pointer each time.
Paul Tomblin
It depends on what type of list you use. I think you're right though, using get would never be faster, and sometimes slower.
Bill the Lizard
+1  A: 

The only way to know for sure is to benchmark it, and even that is not as simple as it may sound. The JIT compiler can do very unexpected things to your code.

Jouni K. Seppänen
+2  A: 

The for-each loop should generally be preferred. The "get" approach may be slower if the List implementation you are using does not support random access. For example, if a LinkedList is used, you would incur a traversal cost, whereas the for-each approach uses an iterator that keeps track of its position in the list. More information on the nuances of the for-each loop.

Zach Scrivena
+6  A: 

All these loops do the exact same, I just want to show these before throwing in my two cents.

First, the classic way of looping through List:

for(int i=0;i<strings.size();i++) { /* do something using strings.get(i) */ }

Second, the preferred way since it's less error prone (how many times have YOU done the "oops, mixed the variables i and j in these loops within loops" thing?).

for(String s : strings) { /* do something using s */ }

Third, the micro-optimized for loop:

int size = strings.size();
for(int i=0;++i<=size;) { /* do something using strings.get(i) */ }

Now the actual two cents: At least when I was testing these, the third one was the fastest when counting milliseconds on how long it took for each type of loop with a simple operation in it repeated a few million times - this was using Java 5 with jre1.6u10 on Windows in case anyone is interested.

While it at least seems to be so that the third one is the faster, you really should ask yourself if you want to take the risk of implementing this peephole optimization everywhere in your looping code since from what I've seen, actual looping isn't usually the most time consuming part of any real program (or maybe I'm just working on the wrong field, who knows). And also like I mentioned in the pretext for the Java for-each loop (some refer to it as Iterator loop and others as for-in loop) you are less likely to hit that one particular stupid bug when using it. And before debating how this even can even be faster than the other ones, remember that javac doesn't optimize bytecode at all (well, nearly at all anyway), it just compiles it.

If you're into micro-optimization though and/or your software uses lots of recursive loops and such then you may be interested in the third loop type. Just remember to benchmark your software well both before and after changing the for loops you have to this odd, micro-optimized one.

P Arrayah
Please note that the for loop with ++i<=size is "1-based", e.g. the get-method inside the loop will be called for values 1, 2, 3, etc.
volley
A better way to write the micro-optimized loop isfor(int i=0, size=strings.size();++i<=size;) {}This is preferable because it minimizes the scope of size
Don
+1  A: 

It's always better to use the iterator instead of indexing. This is because iterator is most likely optimzied for the List implementation while indexed (calling get) might not be. For example LinkedList is a List but indexing through its elements will be slower than iterating using the iterator.

Steve Kuo
Thank you for agreeing with me =)
Zach Scrivena
+2  A: 

foreach makes the intention of your code clearer and that is normally preferred over a very minor speed improvement - if any.

Whenever I see an indexed loop I have to parse it a little longer to make sure it does what I think it does E.g. Does it start from zero, does it include or exclude the end point etc.?

Most of my time seems to be spent reading code (that I wrote or someone else wrote) and clarity is almost always more important than performance. Its easy to dismiss performance these days because Hotspot does such an amazing job.

Fortyrunner
A: 

Well, performance impact is mostly insignificant, but isn't zero. If you look at javadoc of RandomAccess interface:

As a rule of thumb, a List implementation should implement this interface if, for typical instances of the class, this loop:

for (int i=0, n=list.size(); i < n; i++)
    list.get(i);

runs faster than this loop:

for (Iterator i=list.iterator(); i.hasNext();)
      i.next();

And for-each loop is using version with iterator, so for ArrayList for example, for-each loop isn't fastest.

Sarmun