Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 循环缓存iterable';谁的推荐信?_Java_Performance_For Loop - Fatal编程技术网

Java 循环缓存iterable';谁的推荐信?

Java 循环缓存iterable';谁的推荐信?,java,performance,for-loop,Java,Performance,For Loop,我可能试图提高效率,但我一直想知道以下两个代码示例中哪一个执行得更快 假设您对一个对象有一个引用,该对象包含一个Strings的ArrayList,并且您希望遍历该列表。以下哪一项更有效(即使只是略微有效) 或 ArrayList stringArray=foo.getStringList(); 用于(字符串s:stringArray) 系统输出打印项次; 如您所见,第二个循环初始化对列表的引用,而不是像第一个示例那样在每次迭代中调用它。除非这个概念完全不正确,而且它们的功能相同,因为Java

我可能试图提高效率,但我一直想知道以下两个代码示例中哪一个执行得更快

假设您对一个对象有一个引用,该对象包含一个
Strings
ArrayList
,并且您希望遍历该列表。以下哪一项更有效(即使只是略微有效)

ArrayList stringArray=foo.getStringList();
用于(字符串s:stringArray)
系统输出打印项次;
如您所见,第二个循环初始化对列表的引用,而不是像第一个示例那样在每次迭代中调用它。除非这个概念完全不正确,而且它们的功能相同,因为Java的内部工作创建了它们自己的引用变量


所以我的问题是,它是哪一个?

没有区别,因为两个循环都只会在循环开始时获取并维护对表达式迭代器的引用。以下是一段摘录自:

增强型for语句相当于以下形式的基本for语句:

我很可能是想提高效率

当然是这样。现在不要尝试1,写一段可读的代码就可以了。作为标准代码,良好且快速是编译器人员最关注的问题。在猜测什么是高效的之前,您确实需要对Java有很多了解(而且您永远无法确定)

如您所见,第二个循环初始化对列表的引用,而不是每次迭代都调用它

第一个循环也是如此。为什么?想必不会。假设
foo.getStringList()
每次调用时都会返回其他内容。你怎么能迭代呢?请注意,使用索引并不重要,因为并非每个
Iterable
都是
列表

for each循环是使用
迭代器的快捷方式。一个
迭代器只获得一次,然后
hasNext
next
被调用。显然,没有地方可以多次评估
Iterable



1使用良好的算法和/或数据结构是另一回事。要避免使用冒泡排序之类的方法。

是的。如果您检查类似(with
javap-v
)的方法的字节码,那么速记表单不会在循环的每次迭代中重新获取迭代器


我不得不回想起CS课程。我认为它们是等价的。您应该能够通过在调试器中运行程序来观察这一点。变量列表中应该有对从
foo.getStringList()
返回的对象的某种引用,我总是使用第一个选项,因为第二个代码上的stringArray的范围很广。我希望保持范围尽可能窄。@Jimmy但是如果您不再使用同一个变量名,而另一个类将继续保留列表,那么范围是否重要?因为即使在第一个循环中,它也会临时保留引用,首先从方法堆栈中弹出的是代码示例1上的引用保持,而不是示例2。除此之外,这真的不重要。感谢您展示Java源代码!现在我知道我可以省略这些语句(我总是做第二个例子)。从技术上讲,你的例子和我的第二个例子一样,因为你没有第二个类来获取列表。@StrongJoshua重点是向你展示字节码,以及它如何只获取
迭代器一次。
for(String s : foo.getStringList())
    System.out.println(s);
ArrayList<String> stringArray = foo.getStringList();
for(String s : stringArray)
    System.out.println(s);
for (I #i = Expression.iterator(); #i.hasNext(); ) {
    VariableModifiersopt TargetType Identifier =
        (TargetType) #i.next();
    Statement
}
public static void main(String[] args) {
    List<String> al = Arrays.asList("a", "b");
    for (String str : al) {
        System.out.println(str);
    }
}
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=4, locals=4, args_size=1
         0: iconst_2
         1: anewarray     #16                 // class java/lang/String
         4: dup
         5: iconst_0
         6: ldc           #18                 // String a
         8: aastore
         9: dup
        10: iconst_1
        11: ldc           #20                 // String b
        13: aastore
        14: invokestatic  #22                 // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
        17: astore_1
        18: aload_1
        19: invokeinterface #28,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
        24: astore_3
        25: goto          45
        28: aload_3
        29: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
        34: checkcast     #16                 // class java/lang/String
        37: astore_2
        38: getstatic     #40                 // Field java/lang/System.out:Ljava/io/PrintStream;
        41: aload_2
        42: invokevirtual #46                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        45: aload_3
        46: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
        51: ifne          28
        54: return