为什么增强的for循环比正常循环更有效

Arc*_*pgc 26 java foreach for-loop

我读到增强的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){
  ....
}
Run Code Online (Sandbox Code Playgroud)

但这是唯一的原因,增强的for循环优于正常的循环吗?在这种情况下,更好地使用normal for循环,因为理解增强的for循环有点复杂.

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

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

Joa*_*uer 51

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

首先要注意的是,对于集合,增强的for循环使用a Iterator,因此如果使用a手动迭代集合,Iterator则应该具有与增强的for循环相同的性能.

增强的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
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,循环1将比循环2和循环3都慢,因为它将在每次迭代中(部分地)遍历列表以找到位置处的元素i.然而,由于使用了一个,循环2和3只会在列表中进一步执行一个元素Iterator.循环2和3也具有几乎相同的性能,因为循环3几乎就是编译器在循环2中编写代码时将产生的结果.

  • @Joachim,差异,最终似乎在引用的示例中随机访问和串行访问集合.对于数组,两种循环类型的行为都相同. (3认同)

小智 8

我对自己今天做的一个小实验感到很惊讶.所以我所做的是我将一定数量的元素插入链表并使用上面提到的三种方法迭代它1)使用高级for循环2)使用Iterator 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);
Run Code Online (Sandbox Code Playgroud)

结果不是我所期待的.以下是3例中经过的时间图. 时间经过的图表

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输入

在这里你可以看到简单的循环比其他循环更好.如果你在上面的代码中发现任何错误,请回复,我会再次检查.在我仔细检查字节码后,我会进一步了解这一点,看看幕后发生了什么.我为这么长的回应道歉,但我喜欢描述性的.菲利普

  • 你有没有重新安排测试用例?第一个实现较慢的原因可能是由于缓存未命中(对象尚未在缓存中)...... (2认同)

Pet*_*rey 7

我读到增强的for循环比循环的正常有效.

实际上有时它对程序的效率较低,但大部分时间它完全相同.

它对开发人员来说更有效率,这通常更为重要

for-each循环在迭代集合时特别有用.

List<String> list = 
for(Iterator<String> iter = list.iterator(); list.hasNext(); ) {
    String s = list.next();
Run Code Online (Sandbox Code Playgroud)

更容易写成(但做同样的事情,所以它对程序来说不再有效)

List<String> list = 
for(String s: list) {
Run Code Online (Sandbox Code Playgroud)

当通过索引访问随机可访问的集合时,使用"旧"循环稍微更有效.

List<String> list = new ArrayList<String>(); // implements RandomAccess
for(int i=0, len = list.size(); i < len; i++) // doesn't use an Iterator!
Run Code Online (Sandbox Code Playgroud)

在集合上使用for-each循环总是使用Iterator,它对随机访问列表的效率稍差.

AFAIK,使用for-each循环对程序来说永远不会更有效,但正如我所说,开发人员的效率往往更为重要.