Fastest way to iterate an Array in Java: loop variable vs enhanced for statement [duplicate]

StackOverflow https://stackoverflow.com/questions/1006395

  •  06-07-2019
  •  | 
  •  

Question

This question already has an answer here:

In Java, is it faster to iterate through an array the old-fashioned way,

for (int i = 0; i < a.length; i++)
    f(a[i]);

Or using the more concise form,

for (Foo foo : a)
    f(foo);

For an ArrayList, is the answer the same?

Of course for the vast bulk of application code, the answer is it makes no discernible difference so the more concise form should be used for readability. However the context I'm looking at is heavy duty technical computation, with operations that must be performed billions of times, so even a tiny speed difference could end up being significant.

Was it helpful?

Solution

If you're looping through an array, it shouldn't matter - the enhanced for loop uses array accesses anyway.

For example, consider this code:

public static void main(String[] args)
{
    for (String x : args)
    {
        System.out.println(x);
    }
}

When decompiled with javap -c Test we get (for the main method):

public static void main(java.lang.String[]);
  Code:
   0:   aload_0
   1:   astore_1
   2:   aload_1
   3:   arraylength
   4:   istore_2
   5:   iconst_0
   6:   istore_3
   7:   iload_3
   8:   iload_2
   9:   if_icmpge   31
   12:  aload_1
   13:  iload_3
   14:  aaload
   15:  astore  4
   17:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   20:  aload   4
   22:  invokevirtual   #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   25:  iinc    3, 1
   28:  goto    7
   31:  return

Now change it to use an explicit array access:

public static void main(String[] args)
{
    for (int i = 0; i < args.length; i++)
    {
        System.out.println(args[i]);
    }
}

This decompiles to:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   aload_0
   4:   arraylength
   5:   if_icmpge   23
   8:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:  aload_0
   12:  iload_1
   13:  aaload
   14:  invokevirtual   #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   17:  iinc    1, 1
   20:  goto    2
   23:  return

There's a bit more setup code in the enhanced for loop, but they're basically doing the same thing. No iterators are involved. Furthermore, I'd expect them to get JITted to even more similar code.

Suggestion: if you really think it might make a significant difference (which it would only ever do if the body of the loop is absolutely miniscule) then you should benchmark it with your real application. That's the only situation which matters.

OTHER TIPS

This falls squarely in the arena of micro-optimization. It really doesn't matter. Stylistically I always prefer the second because it's more concise, unless you need the loop counter for something else. And that's far more important than this kind of micro-optimization: readability.

That being said, For an ArrayList there won't be much difference but a LinkedList will be much more efficient with the second.

Measure it. The answer on all performance-questions can depend on VM-version, processor, memory-speed, caches etc. So you have to measure it for your particular platform.

Personally I would prefer the second variant, because the intention is more clear. If performance becomes a problem I can optimize it later anyways - if that code really is important for the performance of the whole application.

For a LinkedList:

for(ClassOfElement element : listOfElements) {
  System.out.println(element.getValue());
}

It was answered before:

Is there a performance difference between a for loop and a for-each loop?

On an array, or RandomAccess collection you can get a tiny increase in speed by doing:

List<Object> list = new ArrayList<Object>();

for (int i=0, d=list.size(); i<d; i++) {
    something(list.get(i));
}

But I wouldn't worry in general. Optimisations like this wont make more than 0.1% difference to your code. Try invoking java with -prof to see where your code is actually spending its time.

Even faster is to use the ParallelArray of the fork-join framework (if you have large enough dataset).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top