【问题标题】:Java for loop vs. while loop. Performance difference?Java for 循环与 while 循环。性能差异?
【发布时间】:2010-11-13 00:30:39
【问题描述】:

假设我有以下代码,有三个 for 循环来做某事。如果我将最外层的 for 循环更改为 while 循环,它会运行得快吗?谢谢~~

int length = 200;
int test = 0;
int[] input = new int[10];

for(int i = 1; i <= length; i++) {
    for (int j = 0; j <=length - i; j++) {
        for (int k = 0; k < length - 1; k++) {
            test = test + input[j + k];
        }
    }
}

【问题讨论】:

  • 它将优化为 test = 0;因为没有填充数组所以 test = test + input[j + k];永远为零。
  • 时间!也是 idk java,但我知道在 perl 中,C 风格的 for 循环比 while 循环慢,尤其是在读取文件的情况下。

标签: java for-loop while-loop


【解决方案1】:

for 循环和while 循环都是迭代语句,但都有各自不同的特点。

语法

While 循环

//setup counter variable
int counter = 0;

while ( condition) {

    //instructions 

    //update counter variable
    counter++;  //--> counter = counter + 1;

}

For循环

for (initialization; condition; iteration){
    //body of for loop
}

for 循环的所有声明 (初始化、条件、迭代) 都位于循环体的顶部。相反,在while 循环中,只有初始化和条件位于循环体的顶部,而迭代可以写在循环体的任何位置。

for 和 while 循环的主要区别

  1. for 循环中,初始化、条件检查以及迭代变量的递增或递减仅在循环的语法中显式完成。相反,在While 循环中,我们只能在循环的语法中初始化和检查条件。

  2. 当我们知道循环执行中必须发生的迭代次数时,我们使用 for 循环。另一方面,如果我们不知道循环中必须发生的迭代次数,那么我们使用while 循环。

  3. 如果未能将条件语句放入for 循环中,则会导致循环的无限迭代。相反,如果您没有在while 循环中放置条件语句,则会导致编译错误。

  4. for 循环语法中的初始化语句仅在循环开始时执行一次。相反,如果while循环在其语法中带有初始化语句,那么while循环中的初始化语句将在每次循环迭代时执行。

  5. for 循环中的迭代语句将在循环体执行后执行。相反,迭代语句可以写在while循环体中的任何地方,所以在`while循环体中可能有一些语句在迭代语句执行之后执行。

【讨论】:

    【解决方案2】:

    你可以自己计算。

    int length = 200;
    int test = 0;
    int[] input = new int[10];
    
    long startTime = new Date().getTime();
    
    for(int i = 1; i <= length; i++) {
        for (int j = 0; j <=length - i; j++) {
            for (int k = 0; k < length - 1; k++) {
                test = test + input[j + k];
            }
        }
    }
    
    long endTime = new Date().getTime();
    long difference = endTime - startTime;
    System.out.println("For - Elapsed time in milliseconds: " + difference);
    
    
    test = 0;
    input = new int[10];
    
    int i = 0, j = 0, k = 0;
    
    startTime = new Date().getTime();
    
    while(i < length) {
        while(j <= length - i ) {
            while(k < length - 1) {
                test = test + input[j + k];
                k++;
            }
            j++;
        }
        i++;
    }
    
    endTime = new Date().getTime();
    difference = endTime - startTime;
    System.out.println("While - Elapsed time in milliseconds: " + difference);
    

    【讨论】:

      【解决方案3】:

      不,这不会有很大的不同,唯一的问题是,如果您的嵌套循环可能需要考虑切换,例如出于组织目的,您可能希望在外部使用 while 循环并使用 for 语句在里面。这不会影响性能,但只会让您的代码看起来更干净/有条理

      【讨论】:

        【解决方案4】:

        基于此:https://jsperf.com/loops-analyze(不是我创建的)while 循环通常比 for 循环慢 22%。至少在 Javascript 中是这样。

        【讨论】:

          【解决方案5】:

          【讨论】:

          • 链接中的结论表明迭代器机制是循环列表中最慢的方法。 For 和 While 循环之间的性能差别不大。
          • 文章甚至没有说While循环比For循环快。
          【解决方案6】:

          有没有人试过这样...

          int i = 20;
          while (--i > -1){
              // do stuff
          }
          

          相比:

          for (int i = 0; i < 20; i++){
              // do Stuff
          }
          

          【讨论】:

            【解决方案7】:

            有人建议测试whilefor 循环,所以我创建了一些代码来测试while 循环或for 循环是否更快;平均而言,超过 100,000 次测试,while 循环在大约 95% 的时间内更快。我可能编码不正确,我对编码很陌生,还考虑到如果我只运行了 10,000 个循环,它们最终在运行期间是相当均匀的。

            edit 当我去测试更多试验时,我没有移动所有数组值。已修复此问题,以便更轻松地更改您运行的试验次数。

            import java.util.Arrays;
            
            class WhilevsForLoops {
            
             public static void main(String[] args) {
            
            final int trials = 100; //change number of trials
            final int trialsrun = trials - 1;
            
            boolean[] fscount = new boolean[trials]; //faster / slower boolean
            int p = 0; // while counter variable for for/while timers
            
            
            
            while (p <= trialsrun) {
                 long[] forloop = new long[trials];
                 long[] whileloop = new long[trials];
            
                 long systimeaverage; 
                 long systimenow = System.nanoTime();
                 long systimethen = System.nanoTime();
            
                 System.out.println("For loop time array : ");
                 for (int counter=0;counter <= trialsrun; counter++) {
                     systimenow = System.nanoTime();
                     System.out.print(" #" + counter + " @");
                     systimethen = System.nanoTime();
                     systimeaverage = (systimethen - systimenow);
                     System.out.print( systimeaverage + "ns |");
            
                     forloop[counter] = systimeaverage; 
                 }
            
                 int count = 0;
                 System.out.println(" ");
                 System.out.println("While loop time array: ");
                 while (count <= trialsrun) {
                     systimenow = System.nanoTime();
                     System.out.print(" #" + count + " @");
                     systimethen = System.nanoTime();
                     systimeaverage = (systimethen - systimenow);
                     System.out.print( systimeaverage + "ns |");
            
                     whileloop[count] = systimeaverage;
                     count++;
                 }
            
            
                 System.out.println("===============================================");
                 int sum = 0;
            
                 for (int i = 0; i <= trialsrun; i++) {
                    sum += forloop[i];
                 }
            
                 System.out.println("for loop time average: " + (sum / trials) + "ns");
            
                 int sum1 = 0;
            
                 for (int i = 0; i <= trialsrun; i++) {
                     sum1 += whileloop[i];
                 }
                 System.out.println("while loop time average: " + (sum1 / trials) + "ns");
            
            
            
                 int longer = 0;
                 int shorter = 0;
                 int gap = 0;
            
                 sum = sum / trials;
                 sum1 = sum1 / trials; 
            
                 if (sum1 > sum) {
                    longer = sum1;
                    shorter = sum;
                 }
                 else {
                    longer = sum;
                    shorter = sum1;
                 }
            
                 String longa;
            
                 if (sum1 > sum) {
                    longa = "~while loop~";
                 }
                 else {
                     longa = "~for loop~";
                 }
            
                 gap = longer - shorter; 
                 System.out.println("The " + longa + " is the slower loop by: " + gap + "ns");
                 if (sum1 > sum) {
                 fscount[p] = true; }
                 else {
                     fscount[p] = false;
                 }
                 p++;
            }
            
                int forloopfc=0;
                int whileloopfc=0;
            
                System.out.println(Arrays.toString(fscount));
            
                for(int k=0; k <= trialsrun; k++) {
                    if (fscount[k] == true) {
                        forloopfc++; }
                        else {
                            whileloopfc++;}
            
                }
            
                System.out.println("--------------------------------------------------");
            
                System.out.println("The FOR loop was faster: " + forloopfc + " times.");
                System.out.println("The WHILE loop was faster: " + whileloopfc + " times.");
             }
            
            }
            

            【讨论】:

              【解决方案8】:

              这里有一个有用的link 对有关此事的文章

              据此,While 和 For 几乎快两倍,但两者是相同的。

              但是这篇文章写于 2009 年,所以我在我的机器上试了一下,结果如下:

              • 使用 java 1.7:Iterator 比 For 和 While 快大约 20%-30%(它们仍然相同)
              • 使用 java 1.6:Iterator 比 For 和 While 快大约 5%(它们仍然相同)

              所以我想最好的办法是在你自己的版本和机器上计时并从中得出结论

              【讨论】:

              • 在任何安全语言中,使用迭代器通常更快,因为解释器/编译器可以省略边界检查。
              【解决方案9】:

              不会有性能差异。试试看!

              JVM 和编译器会将两个循环都变成类似

                  label:
                     ;code inside your for loop.
                  LOOP label
              

              【讨论】:

                【解决方案10】:

                for 和 while 的区别在于语义

                • 在 while 循环中,只要条件为真,您就会循环,这可能会有很大差异,因为您可能会在循环中使用评估 while 条件来修改变量。
                • 通常,在 for 循环中,您会循环 N 次。这个 N 可以是可变的,但直到 N 循环结束时才会移动,因为通常开发人员不会修改循环条件中评估的变量。

                这是帮助他人理解您的代码的一种方式。您没有义务不修改 for 循环变量,但这是一种常见(且良好)的做法。

                【讨论】:

                  【解决方案11】:

                  不,改变循环的类型无关紧要。

                  唯一可以让它更快的是循环嵌套更少,循环的值也更少。

                  for 循环和while 循环之间的唯一区别是定义它们的语法。根本没有性能差异。

                  int i = 0;
                  while (i < 20){
                      // do stuff
                      i++;
                  }
                  

                  等同于:

                  for (int i = 0; i < 20; i++){
                      // do Stuff
                  }
                  

                  (实际上 for 循环要好一些,因为 i 将在循环之后超出范围,而 i 将停留在 while 循环案例中。)

                  for 循环只是语法上更漂亮的循环方式。

                  【讨论】:

                  • 您可以在 i 周围添加范围,以便在完成后将其从堆栈中删除:D
                  • 由于 continue 的行为方式,for 循环和 while 循环实际上略有不同。递增将始终发生在 for 循环中,而 while 循环中的 continue 会跳过它,从而导致循环永远继续。
                  • 为什么这不是正确的答案?恕我直言,这准确解释了如何使用这些循环。
                  【解决方案12】:

                  即使 while 循环比 for 循环快的假设是正确的(事实并非如此),您必须更改/优化的循环也不会是外部循环,而是内部循环,因为那些是执行更多次。

                  【讨论】:

                    【解决方案13】:

                    这种微优化毫无意义。

                    • while 循环不会更快。
                    • 循环结构不是你的瓶颈。
                    • 首先优化您的算法。
                    • 更好的是,不要先优化。仅在您发现您的算法确实存在不依赖于 I/O 的瓶颈之后进行优化。

                    【讨论】:

                      【解决方案14】:

                      你不能把它改成while来优化它。

                      你可以通过改变线路来增加速度非常非常非常小

                      for (int k = 0; k < length - 1; k++) {
                      

                      通过

                      for (int k = 0; k < lengthMinusOne; k++) {
                      

                      其中lengthMinusOne 是在之前计算的

                      这个减法只是计算几乎 (200x201/2) x (200-1) 次,它对计算机来说是很少的数字:)

                      【讨论】:

                      • Java 编译器现在通常会优化该调用。但从技术上讲,您认为更快是正确的。
                      • 嘿,我有一半希望有人建议将 k++ 更改为 ++k :D
                      • 您将节省非常非常非常少的编译时间。现在大多数编译器都支持这样的优化检查stackoverflow.com/questions/5981460/…
                      【解决方案15】:

                      看看你的算法!您是否事先知道数组中的哪些值被多次添加?

                      如果您知道可以减少循环次数并提高性能。

                      【讨论】:

                        【解决方案16】:

                        只有在使用多线程或多处理器编程时才有意义。然后它还取决于您如何将循环分配给各种处理器/线程。

                        【讨论】:

                          【解决方案17】:

                          不,您的循环次数仍然完全相同。完全没关系。

                          【讨论】:

                            猜你喜欢
                            • 2020-09-04
                            • 1970-01-01
                            • 1970-01-01
                            • 2014-01-11
                            • 2017-07-14
                            • 2021-03-27
                            • 2010-11-08
                            • 2015-08-28
                            相关资源
                            最近更新 更多