I think your best option is a foreach:
for (Item item : array) {
// Do stuff
}
The compiler optimizes it for you, and it is easier to read. Hooray!
Optimizes, you say? Indeed. Usually it won't make a difference, but if it's easier to read AND faster, why not do it?
Consider this class:
final int SIZE = 3;
final String[] a = new String[SIZE];
void doStuff(String s){}
void useLength(){
for (int i = 0; i < a.length; i++) {
doStuff(a[i]);
}
}
void useConstant(){
for (int i = 0; i < SIZE; i++) {
doStuff(a[i]);
}
}
void useForEach(){
for (String s : a) {
doStuff(s);
}
}
Decompiling, we get this code:
void useLength();
Code:
0: iconst_0
1: istore_1
2: iload_1
3: aload_0
4: getfield #4 // Field a:[Ljava/lang/String;
7: arraylength
8: if_icmpge 27
11: aload_0
12: aload_0
13: getfield #4 // Field a:[Ljava/lang/String;
16: iload_1
17: aaload
18: invokevirtual #5 // Method doStuff:(Ljava/lang/String;)V
21: iinc 1, 1
24: goto 2
27: return
So, if the array is a field, using length will load the field twice per iteration. This can make a difference if the field causes a flush (e.g., if it is volatile, or the JIT is in a bad mood, etc). It also isn't thread safe if the enclosing object is accessed by concurrent threads (the array can have changed between ops 7 and 17).
void useConstant();
Code:
0: iconst_0
1: istore_1
2: iload_1
3: iconst_3
4: if_icmpge 23
7: aload_0
8: aload_0
9: getfield #4 // Field a:[Ljava/lang/String;
12: iload_1
13: aaload
14: invokevirtual #5 // Method doStuff:(Ljava/lang/String;)V
17: iinc 1, 1
20: goto 2
23: return
This does only one field access per iteration, but if the stars are right, it can still cost us. It also has rather unspecified behaviour if the field changes value.
Foreach does things slightly differently:
void useForEach();
Code:
0: aload_0
1: getfield #4 // Field a:[Ljava/lang/String;
4: astore_1
5: aload_1
6: arraylength
7: istore_2
8: iconst_0
9: istore_3
10: iload_3
11: iload_2
12: if_icmpge 32
15: aload_1
16: iload_3
17: aaload
18: astore 4
20: aload_0
21: aload 4
23: invokevirtual #5 // Method doStuff:(Ljava/lang/String;)V
26: iinc 3, 1
29: goto 10
32: return
Only one field access, and one array length check! It is roughly equivalent to:
void useForEach(){
String[] localArr = arr;
for (int i = 0, length = arr.length; i < length; i++) {
doStuff(localArr[i]);
}
}
.lengthis an attribute, not a method. As it does not need to be computed (as can be Collection.size()), it is useless to introduce a new variable.lengthvalue is a attribute, not a method, so either using.lengthor your constant should incur the same lookup time (theoretically, I could be wrong). Either way the amount of difference would be so minuscule that I doubt you'd see any visible performance gains. If you don't need index information or to modify the array when looping you should consider using the "foreach" construct:for (int i : array) { /* code */ }array.length. It makes it clear what you are trying to do, and somebody reading the code does not have to go lookup how/where the variable is being used.