31

(A question for those who know well the JVM compilation and optimization tricks... :-)

Is there any of the "for" and "foreach" patterns clearly superior to the other?

Consider the following two examples:

public void forLoop(String[] text)
{
    if (text != null)
    {
        for (int i=0; i<text.length; i++)
        {
            // Do something with text[i]
        }
    }
}

public void foreachLoop(String[] text)
{
    if (text != null)
    {
        for (String s : text)
        {
            // Do something with s, exactly as with text[i]
        }
    }
}

Is forLoop faster or slower than foreachLoop?

Assuming that in both cases the text array did not need any do sanity checks, is there a clear winner or still too close to make a call?

EDIT: As noted in some of the answers, the performance should be identical for arrays, whereas the "foreach" pattern could be slightly better for Abstract Data Types like a List. See also this answer which discusses the subject.

1
  • Answer 256859 does cover my question but somehow it did not pop up in the searches I did. Thanks everyone! Commented Feb 10, 2012 at 11:23

5 Answers 5

77

From section 14.14.2 of the JLS:

Otherwise, the Expression necessarily has an array type, T[]. Let L1 ... Lm be the (possibly empty) sequence of labels immediately preceding the enhanced for statement. Then the meaning of the enhanced for statement is given by the following basic for statement:

T[] a = Expression;
L1: L2: ... Lm:
for (int i = 0; i < a.length; i++) {
        VariableModifiersopt Type Identifier = a[i];
        Statement
}

In other words, I'd expect them to end up being compiled to the same code.

There's definitely a clear winner: the enhanced for loop is more readable. That should be your primary concern - you should only even consider micro-optimizing this sort of thing when you've proved that the most readable form doesn't perform as well as you want.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 for emphasizing the importance of readability/understandability!
@Kevin: Do you have a benchmark for that that you can share? This isn't a jit optimization - it's just how the loop is compiled for arrays.
@JonSkeet I thought I did, but now I can't replicate what I saw just the other day. Comment retracted.
4

You can write your own simple test, which measure the execution time.

long start = System.currentTimeMillis();
forLoop(text);
long end = System.currentTimeMillis();
long result = end - start;

result is execution time.

5 Comments

Seemingly yes, but in reality there are too many other parameters affecting such a measurement (even the order in which the tests are executed) to consider it reliable.
Yeah, tests that measure execution time and should have a certain degree of validity are never “simple.”
@PNS: It's still better to measure (in a realistic situation) than it is to speculate. With measurement, you can only be somewhat misled; with speculation, you can go wildly wrong.
I've found that foreach's performance time is less than for loop while executing same block of code.
Please, never benchmark like this! There are many pitfalls to micro benchmarking. E.g., you should do "warm-up runs" first, because what really matters is the performance after the JIT realizes this is something that should be optimized and kicks in. To properly do micro benchmarking, there are tools like JMH, have a look. Also, you should never measure time with System.currentTimeMillis() as it can be affected by clock adjustments (NTP etc.). Always use System.nanoTime(), even if you don't need nano second precision.
3

Since you are using an array type, the performance difference wouldn't matter. They would end up giving the same performance after going through the optimization funnel.

But if you are using ADTs like List, then the forEachLoop is obviously the best choice compared to multiple get(i) calls.

1 Comment

plus yes, you shouldn't rely on such optimization details, you can be disappointed at any time.
3

You should choose the option which is more readable almost every time, unless you know you have a performance issue.

In this case, I would say they are guaranteed to be the same.

The only difference is you extra check for text.length which is likely to be slower, rather than faster.

I would also ensure text is never null statically. e.g. using an @NotNull annotation. Its better to catch these issues at compile/build time (and it would be faster)

Comments

1

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. For details follow this post.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.