In general the gain will be minimal in the case of ArrayList
that calls a method and has some cost.
Have tested the OS . The gain really is very low and it only pays to worry about it if the body of the loop is very fast, then the method call several times can weigh.
In the case of array there will be a smaller gain still. Both access a variable directly, the only difference is that access to the property will require indirect access (through a pointer) to the object and access to the local variable will be done directly there.
I think not in Java, but in C # even a property would be done inline having the same gain as array .
Optimization
I also do not say that there is any harm in always prefer to cache the value before. Unless the compiler or JITter does some optimization by having the size checked inside the loop and when the size is checked out the optimization does not occur. There is usually a big gain in removing the access-band overflow check inside the loop if the / JITter compiler can identify that it will never go out of bounds. One way to ensure this is to use for each
. Another is the compiler being smart and checking that the condition plus usage always produces indexes within the range. The check is done inside the loop. What is out of the loop is not reliable information, it may even give error as shown below.
Semantics
But note that in addition to performance you may have a better reason to do the size cache. The semantics are different in both cases.
You should not do this, but if you change the size of the data collection inside the loop and the size has been cached outside of it, it may not have the expected result. The data that indicates the end of the loop no longer beats the reality of the object.
I gave an example showing the difference:
import java.util.*;
import java.lang.*;
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
ArrayList<Integer> x = new ArrayList<Integer>();
x.add(1); x.add(2); x.add(3); x.add(4); x.add(5);
for (int i = 0; i < x.size(); i++) {
if (i % 2 == 0) { //retira os elementos pares
x.remove(i);
}
System.out.println("Tamanho atual = " + x.size() + ", i = " + i); //só para ajudar visualizar
}
System.out.println("---");
for (int i = 0; i < x.size(); i++) {
System.out.println(x.get(i));
}
System.out.println("---------------------");
x = new ArrayList<Integer>();
x.add(1); x.add(2); x.add(3); x.add(4); x.add(5);
int tamanho = x.size();
for (int i = 0; i < tamanho; i++) {
if (i % 2 == 0) {
x.remove(i);
}
System.out.println("Tamanho atual = " + x.size() + ", i = " + i); //só para ajudar visualizar
}
System.out.println("---");
for (int i = 0; i < x.size(); i++) {
System.out.println(x.get(i));
}
}
}
See how it looks in ideone . That gives error by bursting the existing band, because the loop is with an information lagged.
There is another problem with different semantics that is not the case with the question, but it is worth the information. You might use a method to get a value and decide whether to close the loop. This method can have a side effect. Is it desirable for this effect to occur at each iteration or should it only occur once? This is important.