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;
}
}
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With