A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 郭宁 中级黑马   /  2012-5-29 08:44  /  2993 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1. int v1=100000;
  2.         int v2=10000;
  3.         int v3=10;
  4.         for(int i=0; i<v1;i++)
  5.                 for(int j=0; j<v2; j++)
  6.                         for(int k=0; k<v3; k++)
  7.                                 do();


  8. for(int i=0; i<v3;i++)
  9.                 for(int j=0; j<v2; j++)
  10.                         for(int k=0; k<v1; k++)
  11.                                 do();
复制代码
这两个循环哪个效率高 , 为什么??

点评

循环应该保持大圈套小圈的原则,也就是你的第二种,效率的提高原因是栈深度的问题,而如果测试,你最好使用外部变量,做稳定的乘除法运算  发表于 2012-5-30 12:29

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

10 个回复

倒序浏览
本帖最后由 李哲 于 2012-5-29 09:56 编辑

直觉是第二种。{:soso_e100:}
但是经过测试,似乎直觉不靠谱。
第一种
  1. public class ForCompare {

  2.         /**
  3.          * @param args
  4.          */
  5.         public static void main(String[] args) {
  6.                 // TODO Auto-generated method stub
  7.                 long all=0;
  8.                 long allTime=0;
  9.                 while(all<50){
  10.                     int v1=100;
  11.                 int v2=10;
  12.                 int v3=1;
  13.                 long l2=System.currentTimeMillis();
  14.        
  15.        
  16.                for(int i=0; i<v1;i++){
  17.                        for(int j=0; j<v2; j++){
  18.                                for(int k=0; k<v3; k++){
  19.                                       
  20.                                        AAA();
  21.                                }
  22.                        }
  23.                }
  24.                 long l3=System.currentTimeMillis();
  25.                
  26.                 System.out.println(l3 - l2);
  27.                 all++;
  28.                 allTime+=l3 - l2;
  29.                 
  30.                 }

  31.                 System.out.println(allTime);
  32.                 //51906
  33.                 //593
  34.                 //250,266,266,250,250
  35.                 //1062,1172,1094,1125,1062,1094,1047,1110,1063,1156,1093
  36.         }
  37.         public static void AAA(){
  38.                 for (int i = 0; i < 2; i++) {
  39.                         System.out.println("hehe");
  40.                        
  41.                 }
  42.         }

  43. }
复制代码
第二种
  1. public class CopyOfForCompare1 {

  2.         /**
  3.          * @param args
  4.          */
  5.         public static void main(String[] args) {
  6.                 // TODO Auto-generated method stub
  7.                
  8.         long all=0;
  9.         long allTime=0;
  10.         while(all<50){
  11.             int v1=100;
  12.         int v2=10;
  13.         int v3=1;
  14.         long l2=System.currentTimeMillis();


  15.         for(int i=0; i<v3;i++){
  16.                 for(int j=0; j<v2; j++){
  17.                         for(int k=0; k<v1; k++){
  18.                                
  19.                                 AAA();
  20.                         }}}
  21.         long l3=System.currentTimeMillis();
  22.       
  23.         System.out.println(l3 - l2);
  24.         all++;
  25.         allTime+=l3 - l2;
  26.         
  27.         }

  28.         System.out.println(allTime);
  29.         //54234
  30.         //625
  31.         //234,265,250,266,266
  32.         //1141,1125,1156,1109,1094,1141,1156,1141,1031,1109
  33. }
  34. public static void AAA(){
  35.         for (int i = 0; i < 2; i++) {
  36.                 System.out.println("hehe");
  37.                
  38.         }
  39. }

  40. }
复制代码
下面的那些注释为修改v1,v2,v3,all之后得到的结果。

点评

你这个测试应该看起来没什么问题,但是循环范围比较小,并且时间精度不够,你可以试试用System.nano这个方法,他的精度是毫秒的10亿分之一  发表于 2012-5-30 12:32

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
循环次数一样,理论上来说效率都是一样的低,时间复杂度为O(n^3)么。
我将lz的v1改成1000,v2 改成100,测试过时间确实差别不大
当然一般情况下写代码遵循的原则是外层循环数字小,内层循环数字大的原则,至于为什么,好像和cpu的catch命中率之类的有关系
lz可以看下这篇帖子http://topic.csdn.net/u/20071206/20/5ae1a8f9-fab5-443c-a2ea-af1d755f5de1.html
我个人觉得基本上对for循环的效率不是我们需要太过关心的东西,不如想想怎么样避免使用三重for比较靠谱。

点评

java跟c++是不一样的,很多区别,否则很早的java书上就不会前2章做对比了,循环在应用中是最常见的,可能最多你会嵌套几十个,这也很正常  发表于 2012-5-30 12:35
回复 使用道具 举报
第一种的时间复杂度为:O(v1v2v3);
第二中的时间复杂度是:O(v3v2v1);
又因为:v1v2v3=v3v2v1;
所以他们的时间复杂度一样,
所以他们的循环效率相等。

点评

你可以敲代码试试,一个循环20亿次,一个循环1000次,光说是没用的,我也希望他们是一样的,可惜不是  发表于 2012-5-30 12:36
回复 使用道具 举报
第1种:循环次数为V1*V2*V3
第2种:循环次数为V3*V2*V1
SO,一样的.
就像楼上说的,研究这个不如想想怎么样避免使用三重for比较靠谱。
回复 使用道具 举报
第二种 做过测试了 呵呵
代码改了下

public class TestFor {

        /**
         * @param args
         */
public static void main(String[] args) {
        int v1=100;
        int v2=10;
        int v3=1;
        long time1start=System.currentTimeMillis();
      
        for(int i=0; i<v1;i++)
                for(int j=0; j<v2; j++)
                        for(int k=0; k<v3; k++)
                               System.out.print("hello");
        System.out.println();
        long time1end=System.currentTimeMillis();
        System.out.println((time1end-time1start)+"millis");

        long time2start=System.currentTimeMillis();
        for(int i=0; i<v3;i++)
                for(int j=0; j<v2; j++)
                        for(int k=0; k<v1; k++)
                                System.out.print("world");

        System.out.println();
        long time2end=System.currentTimeMillis();
        System.out.println((time2end-time2start)+"millis");
        }

}
反复运行证明第二种效率明显高于第一种
回复 使用道具 举报
朝哥 中级黑马 2012-5-29 09:36:26
7#
效率是什么?我们先把效率在java中的意思搞清楚。效率就是java运行代码的最少个数。在这里可以指for循环的次数,当你得出的结果需要1000多循环和10个循环,你会选择哪种呢?
把代码简化一下

        for(int i=1; i<2;i++)
                for(int j=1; j<3; j++)
                        for(int k=1; k<4; k++)
                                do();


for(int i=1; i<4;i++)
                for(int j=1; j<3; j++)
                        for(int k=1; k<2; k++)
                                do();

说实话,你这个代码没有可比性,为什么,比如说通过3个for循环来去三位数,你可以发现
上面一种取的范围为111-123
而下面一种取值的范围为111-321
lz看出来了吗?没可比性。你只是单纯的在字面上理解这两个差不多,其实差很多。

点评

你还是没彻底活用循环,把循环当成多维矩阵,怎么摆那是敲代码的人的设计,并不是就不能换个摆法  发表于 2012-5-30 12:39
回复 使用道具 举报
朝哥 中级黑马 2012-5-29 09:40:03
8#
ls的真牛b,明显不能比的嘛,他们取值的范围根本就不同,写了这么多完全在意淫嘛。
回复 使用道具 举报
嗨,哥们你不妨换个角度去思考一下,他们的总循环次数是相等的你没发现吗?
v1 x  v2  x v3 = v3  x v2  x b1.
所以效率是一样的,因为总循环次数是一样的。
回复 使用道具 举报
想这种情况只能依题而言,比如说你第一次循环就取得结果,二者没区别
你要是取221,第一个循环做不了,所以说你不知道结果的情况,效率是没可比性的。有了结果你分析二者执行了的循环循环数是不是一样的。一样的效率一样,不一样效率也不一样。
回复 使用道具 举报
whocases 黑马帝 2012-5-29 10:23:22
11#
楼上的童鞋说的都挺好的

在实际的开发中,很少用三个for循环嵌套的。两个for的倒是常见。每增加一个for循环的话,效率就是低很多。虽然有时它很方便。
原因:
for循环嵌套太多的话
1.不利于代码优化,
2.效率不高

没事玩玩的for嵌套的话,相当的可以;

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马