Reputation: 15046
How inefficient is that:
List<Object> getList(){
return new LinkedList<Object>();
}
void foo(){
for(Object o: getList()){
do something with o;
}
}
in compare with that:
List<Object> getList(){
return new LinkedList<Object>();
}
void foo(){
List<Object> os = getList();
for(Object o: os){
do something with o;
}
}
Upvotes: 2
Views: 136
Reputation: 24780
In
for(Object o: getList()) {
getList()
is an expression that is evaluated once and its result (a reference an iterator
of the list) kept. If you fear that this code calls getList()
at each iteration, it is not true (if it was, it would be an infinite loop if the list had at least one element as each time the iteration would start with a new list, at the 0 element).
Upvotes: 5
Reputation: 500267
There won't be any perceptible difference.
I've compiled the following code:
import java.util.LinkedList;
import java.util.List;
public class Test1 {
static List<Object> getList(){
return new LinkedList<Object>();
}
void process(Object o) {}
void foo1(){
for(Object o: getList()){
process(o);
}
}
void foo2(){
List<Object> os = getList();
for(Object o: os){
process(o);
}
}
}
The bytecodes for foo1
and foo2
are as follows:
void foo1();
Code:
0: invokestatic #26; //Method getList:()Ljava/util/List;
3: invokeinterface #28, 1; //InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
8: astore_2
9: goto 24
12: aload_2
13: invokeinterface #34, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
18: astore_1
19: aload_0
20: aload_1
21: invokevirtual #40; //Method process:(Ljava/lang/Object;)V
24: aload_2
25: invokeinterface #42, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
30: ifne 12
33: return
void foo2();
Code:
0: invokestatic #26; //Method getList:()Ljava/util/List;
3: astore_1
4: aload_1
5: invokeinterface #28, 1; //InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
10: astore_3
11: goto 26
14: aload_3
15: invokeinterface #34, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
20: astore_2
21: aload_0
22: aload_2
23: invokevirtual #40; //Method process:(Ljava/lang/Object;)V
26: aload_3
27: invokeinterface #42, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
32: ifne 14
35: return
As you can see for yourself, the bytecodes for the two loops are identical. The only difference is that foo2
stores and loads the list reference in a local variable at the start.
One might argue that a better optimizing compiler may be able to eliminate os
altogether, producing identical code for both functions.
Upvotes: 4
Reputation: 93020
In fact the former is more efficient in theory, because in the latter there is one more reference created.
However this is negligible (really negligible) difference.
Upvotes: 0
Reputation: 43219
As this:
List<Object> os = getList();
only creates a reference and the actual data is not copied, the difference in speed is negligible, perhaps non-existant because it probably will be the same bytecode.
Upvotes: 4