效率如何:
List<Object> getList(){
return new LinkedList<Object>();
}
void foo(){
for(Object o: getList()){
do something with o;
}
}
与之相比:
List<Object> getList(){
return new LinkedList<Object>();
}
void foo(){
List<Object> os = getList();
for(Object o: os){
do something with o;
}
}
答案 0 :(得分:6)
在
for(Object o: getList()) {
getList()
是一个表达式,它被计算一次,并保留其结果(列表的引用iterator
)。如果你担心这个代码在每次迭代时调用getList()
,那就不是真的(如果是,如果每次迭代以新列表开始时列表至少有一个元素,它将是一个无限循环,在0元素。)
答案 1 :(得分:5)
没有任何可察觉的差异。
我编译了以下代码:
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);
}
}
}
foo1
和foo2
的字节码如下:
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
正如您自己看到的,两个循环的字节码是相同的。唯一的区别是foo2
在开始时将列表引用存储并加载到局部变量中。
有人可能会争辩说,更好的优化编译器可以完全消除os
,为两个函数生成相同的代码。
答案 2 :(得分:4)
这样:
List<Object> os = getList();
只创建一个引用并且不复制实际数据,速度差异可以忽略不计,可能是不存在的,因为它可能是相同的字节码。
答案 3 :(得分:0)
事实上,前者在理论上更有效率,因为在后者中还有一个参考创建。
然而,这可以忽略不计(实际上可以忽略不计)。