为什么增强的 for 循环比普通 for 循环更有效

2022-09-01 09:20:08

我在这里读到增强的for循环比正常的for循环更有效:

http://developer.android.com/guide/practices/performance.html#foreach

当我搜索它们的效率之间的差异时,我发现的只是:在正常的for循环的情况下,我们需要一个额外的步骤来找出数组的长度或大小等,

for(Integer i : list){
   ....
}


int n = list.size();
for(int i=0; i < n; ++i){
  ....
}

但这是唯一的原因,增强的for循环比正常的for循环更好吗?在这种情况下,最好使用正常的 for 循环,因为在理解增强的 for 循环时略有复杂。

检查这个有趣的问题:http://www.coderanch.com/t/258147/java-programmer-SCJP/certification/Enhanced-Loop-Vs-Loop

任何人都可以解释这两种类型的for循环的内部实现,或者解释使用增强的for循环的其他原因吗?


答案 1

说增强的 for 循环更有效率有点过于简单化了。它可以是,但在许多情况下,它几乎与老式循环完全相同。

首先要注意的是,对于集合,增强的 for 循环使用 ,因此,如果您使用 一个手动迭代集合,那么您应该具有与增强的 for 循环几乎相同的性能。IteratorIterator

增强的 for 循环比天真实现的传统循环更快,如下所示:

LinkedList<Object> list = ...;

// Loop 1:
int size = list.size();
for (int i = 0; i<size; i++) {
   Object o = list.get(i);
   /// do stuff
}

// Loop 2:
for (Object o : list) {
  // do stuff
}

// Loop 3:
Iterator<Object> it = list.iterator();
while (it.hasNext()) {
  Object o = it.next();
  // do stuff
}

在这种情况下,循环 1 将比循环 2 和循环 3 都慢,因为它必须在每次迭代中(部分)遍历列表才能找到位置的元素。但是,循环 2 和 3 在列表中只会进一步执行一个元素,因为使用了 .循环 2 和循环 3 也将具有几乎相同的性能,因为循环 3 几乎完全是编译器在循环 2 中编写代码时将生成的代码。iIterator


答案 2

我自己在我今天用上面提到的几点做的一个小实验中感到惊讶。所以我所做的是,我在一个链接列表中插入了一定数量的元素,并使用上面提到的三种方法对其进行迭代 1)使用高级循环 2)使用迭代器 3) 使用简单循环和 get()
我想像你们这样的程序员可以通过查看代码来更好地理解我做了什么。

long advanced_timeElapsed,iterating_timeElapsed,simple_timeElapsed;
    long first=System.nanoTime();
    for(Integer i: myList){
        Integer b=i;
    }
    long end= System.nanoTime();
    advanced_timeElapsed=end-first;
    System.out.println("Time for Advanced for loop:"+advanced_timeElapsed);
    first=System.nanoTime();
    Iterator<Integer> it = myList.iterator();
    while(it.hasNext())
    {
        Integer b=it.next();
    }
    end= System.nanoTime();
    iterating_timeElapsed=end-first;
    System.out.println("Time for Iterating Loop:"+iterating_timeElapsed);
    first=System.nanoTime();
    int counter=0;
    int size= myList.size();
    while(counter<size)
    {
        Integer b=myList.get(counter);
        counter++;  
    }
    end= System.nanoTime();
    simple_timeElapsed=end-first;
    System.out.println("Time for Simple Loop:"+simple_timeElapsed);

结果不是我所期望的。以下是3种情况下经过的时间图。Time Elapsed Graph

Y 轴时间 已用 X 轴测试用例
测试用例1:10 输入
测试用例2:30 输入
测试用例3:50 输入
测试用例4:100 输入
测试用例5:150 输入
测试用例6:300 输入
测试用例7:500 输入
测试用例8:1000 输入
测试用例9:2000 输入
测试用例10:5000 输入
测试用例11:10000 输入
测试用例12:100000 输入

在这里,您可以看到简单循环的性能比其他循环好得多,如果您在上面的代码中发现任何错误,请回复,我会再次检查。在我挖掘字节码并查看引擎盖下发生的事情后,将进一步更新。我很抱歉这么长的回应,但我喜欢描述。菲利普