我经常遇到一些情况,我希望使用一个强大的for循环来获取某些从某个对象获得的Collection或数组。
e.g。
items = basket.getItems();
for (int item : items) {
// Do something
}
另一种方法是:
for (int item : basket.getItems()) {
// Do something
}
第二个更紧凑,在我看来提高了可读性,特别是当item
变量不会在其他任何地方使用时。
我想知道for语句中的getter是否对性能有任何影响。它会被优化到类似于第一个的东西吗?或者它每次都会访问吸气剂?当然,getItems()
可能会做很慢的事情(例如网络访问等)
问题类似于其他问题,但是指的是集合/数组本身的getter而不是它的大小。但是,最终可能是相同的情况。
答案 0 :(得分:9)
在两种情况下,getItems()
方法只会被调用一次。除了使用额外的局部变量之外,两者之间没有区别。
正如您在JLS 14.14.2中所读到的,增强的for循环大致转换为传统的for循环:
for (I #i = Expression.iterator(); #i.hasNext(); ) { TargetType Identifier = (TargetType) #i.next(); Statement }
#i是一个自动生成的标识符,它与发生增强for语句时的范围(第6.3节)中的任何其他标识符(自动生成的或其他标识符)不同。
从这里可以清楚地看出Expression
只被评估过一次。
答案 1 :(得分:2)
正如您在下面的代码示例中所看到的,在增强型for上,要进行迭代的集合的初始化仅执行一次。因此,第二种选择更紧凑,不会影响性能。
package test;
public class Main {
static class Basket {
int[] items = { 1, 2, 3 };
public int[] getItems() {
System.out.println("in getItems()");
return items;
}
}
public static void main(String[] args) {
Basket basket = new Basket();
for (int item : basket.getItems()) {
System.out.println(item);
}
}
}
答案 2 :(得分:0)
是的,第二个提高了代码的可读性。
如果您从网络获取对象然后在for循环中迭代它,那么我认为它会影响性能,因为您每次都在进行网络访问,这对于执行网络的小/单个对象也是低效的不建议访问。而不是从网络访问中获取一次将其存储在本地并迭代它
因此,第一个选项是在网络访问案例中进行性能优化 如果你的对象是本地的,那么任何方法都可以。不会有太大的性能差异。
答案 3 :(得分:0)
我不认为它每次都会调用getter。如果是这样,它每次都会得到新的列表,Loop不会中断。你可以通过在getter方法中放入简单的 Sysout 来测试它。这两种情况的表现相同。