Java 5 gave us the for-each loops, which should be used where ever possible.
But what is the most efficient idiom if you need to use the index of the array in the block?
// Option (1)
for (int i = array.length - 1; i >= 0; i--) {
// Code.
}
// Option (2)
for (int i = 0; i < array.length; i++) {
// Code.
}
// Option (3)
for (int i = 0, n = array.length; i < n; i++) {
// Code.
}
(Obviously, this won't make a big performance difference in most programs but humor me.) :-)
loops backwards and is hideous. Maybe even cache unfriendly? Or can modern processer detect striding backwards in memory?
is shorter and I can see how the JIT compiler can figure out that
array
never changes and thuslength
is constant so it can essentially replace it with (3). But does it do that? (Assume the JVM is Oracle's Hotspot/Java 7.)is suggested by Joshua Bloch in Item 45 in Effective Java as the fastest option if it's some
Collection.size()
that's the upper bound. But does it also apply to arrays? From the bytecode (see below) I can see that one save anarraylength
instruction per cycle (pre-optimized).
This question about for loops in the Dalvik Virtual Machine, lists (1)-(3) as fastest to slowest. However, the information is from 2008 and Dalvik is much more mature today so I hardly think that's still the case.
Looking at the bytecode generated from the above examples, there are obvious differences:
Compiled from "ForLoops.java"
public class ForLoops extends java.lang.Object{
static int[] array;
public ForLoops();
Code:
0: aload_0
1: invokespecial #10; //Method java/lang/Object."<init>":()V
4: return
public static void forLoop1();
Code:
0: getstatic #17; //Field array:[I
3: arraylength
4: iconst_1
5: isub
6: istore_0
7: goto 13
10: iinc 0, -1
13: iload_0
14: ifge 10
17: return
public static void forLoop2();
Code:
0: iconst_0
1: istore_0
2: goto 8
5: iinc 0, 1
8: iload_0
9: getstatic #17; //Field array:[I
12: arraylength
13: if_icmplt 5
16: return
public static void forLoop3();
Code:
0: iconst_0
1: istore_0
2: getstatic #17; //Field array:[I
5: arraylength
6: istore_1
7: goto 13
10: iinc 0, 1
13: iload_0
14: iload_1
15: if_icmplt 10
18: return
}