一个很简单的问题,但是却又不简单。之所以叫简单的问题是因为内容少,答案不简单是很多人回答不了。废话少说,上题:双重for循环效率问题,外面一千万次,里面一百次……
for(int i=0;i<10000000;i++)
for(int j=0;j<100;j++);for(int i=0;i<100;i++)
for(int j=0;j<10000000;j++);
大家看后说说哪个效率要高些还是说两个都是一样。我本人第一感觉是第一个要快些,后来一想是不是一样的呢?因为计算次数都相等,后来一实验,结果却出人意料。网上有人说下面的快,原因是因为跳的次数少,但是结果却相反,你怎么看呢?

解决方案 »

  1.   

    我认为不同的jdk实现有不同的结果如果某个jdk实现可以重用局部变量区的j,而不是每次都重新分配一个j,那么效率应该和另外一种差不多
      

  2.   

    public class TestFor { /**
     * @param args
     */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    long sum = 0;
    long startTime = System.nanoTime();
    for (int i = 0; i < 10000000; i++)
    for (int j = 0; j < 100; j++) {
    sum += j;
    }
    long endTime = System.nanoTime();
    System.out.println("方法一耗时:" + (endTime - startTime)); sum =0;
    long startTime1 = System.nanoTime();
    for (int i = 0; i < 100; i++)
    for (int j = 0; j < 10000000; j++) {
    sum += j;
    }
    long endTime1 = System.nanoTime();
    System.out.println("方法二耗时:" + (endTime1 - startTime1));
    }
    }
    下面是运行结果,单位是毫秒
    方法一耗时:3279567707
    方法二耗时:2946789382
      

  3.   


    int  = 0;
    long begin = System.currentTimeMillis();
    for(int i=0;i<10000000;i++)
    for(int j=0;j<100;j++){
    ++;
    }
    long use = System.currentTimeMillis()- begin;
    System.out.println(use);
     = 0;

    long begin1 = System.currentTimeMillis();
    for(int i=0;i<100;i++)
    for(int j=0;j<10000000;j++){
    ++;
    }
    long use1 = System.currentTimeMillis()- begin1;
    System.out.println(use1);在下是JDK1.6,这是执行结果:
    1312
    1469
      

  4.   

    测试代码:
    public class Test {
        /**
    * @param args
    */
    public static void main(String[] args) {
    long sum = 0;
    for (int i = 0; i < 10000000; i++)
    for (int j = 0; j < 100; j++) {
    sum += j;
    }
    //以上代码先让jre热热身
    sum = 0;
    long startTime = System.nanoTime();
    for (int i = 0; i < 10000000; i++)
    for (int j = 0; j < 100; j++) {
    sum += j;
    }
    long endTime = System.nanoTime();
    System.out.println("方法一耗时:" + (endTime - startTime)); sum =0;
    long startTime1 = System.nanoTime();
    for (int i = 0; i < 100; i++)
    for (int j = 0; j < 10000000; j++) {
    sum += j;
    }
    long endTime1 = System.nanoTime();
    System.out.println("方法二耗时:" + (endTime1 - startTime1));
    }
    }
    测试结果:IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Windows XP x86-32 j9vmwi3223ifx-20061016 (JIT enabled)
    方法一耗时:26298606107
    方法二耗时:28221543520IBM J9 VM (build 2.4, J2RE 1.6.0 IBM J9 2.4 Windows XP x86-32 jvmwi3260-20080816_22093 (JIT enabled, AOT enabled)
    方法一耗时:14806
    方法二耗时:7822Java HotSpot(TM) Client VM (build 1.5.0_17-b04, mixed mode, sharing)
    方法一耗时:4369540263
    方法二耗时:4234990481Java HotSpot(TM) Client VM (build 16.0-b13, mixed mode, sharing)
    方法一耗时:2188964240
    方法二耗时:1931450785Oracle JRockit(R) (build R28.0.1-21-133393-1.6.0_20-20100512-2132-windows-ia32, compiled mode)
    方法一耗时:4431655140
    方法二耗时:4328235013
    JRockit1.5没装,就没测试了,综上,IBM J91.5做这种循环效率最差,但是J9 1.6做了很好的优化,效率大大提高!另外,如果不给jre热身热身就直接测试是不对的,像sun hotspot jvm,它会在运行时做一些优化
      

  5.   

    同时,在IBM J9 1.5中可以发现,第二种方式的效率比第一种低
      

  6.   

    我也测一下, 也是JDK1.6        int  = 0;
            long begin = System.nanoTime();
            for(int i=0;i<10000000;i++)
                for(int j=0;j<100;j++){
                    ++;
                }
            long use = System.nanoTime()- begin;
            System.out.println(use);
            int  = 0;
            long begin = System.nanoTime();
            for(int i=0;i<100;i++)
                for(int j=0;j<10000000;j++){
                    ++;
                }
            long use = System.nanoTime()- begin;
            System.out.println(use);
    1622690593 1624523508 1622771609
    1497539212 1496512267 1494422615
      

  7.   

    我直接copy运行,几次都是
    14xx
    12xx
    jdk1.6
    嘿~
      

  8.   

    记得以前看过一篇文章,说的是J2ME,至于J2SE不清楚是不是这样的。大家有兴趣看看。JAVA每定义一个变量,如a=5,首先虚拟机会找内存中是否有5,如果有的话,那么就把5给a,如果没有就创建一个5的值,当b=a时,其实内存中只有一个5,相当于共用。b=6时,同理。不过这和数组又不一样,改变a值b值是不变的。如此说来我的第一种快就好解释了,先大后小,大的内存值已经创建,直接赋值,相反需要不断的创建,创建是需要时间的,所以上面比下面快。至于其它版本JDK怎么执行,或者怎么处理内存值还需要深度研究呀~~~
      

  9.   

    这个好玩 ,不同的JDK实现 结果貌视 结果不一样
      

  10.   

    jdk 1.5.0.06
    方法一耗时:2965354815
    方法二耗时:2895023809
      

  11.   

    纯属扯淡,在c语言中可能确实第二种是一种优化,但在java中,是不能拿c语言的东西来套的,jvm本身只是一纸规范,若自己实现一个jdk,完全可以优化第一种方式,让它的效率比第二种高,IBM J9 1.5的实现第一种方式就比第二种方式效率稍高点
      

  12.   

    测试代码有问题,由于 Java HotSpot 的关系,写在 main 方法前面的代码执行会耗时一些,后面的代码会快一些,你把两种循环换个个,就会发现了。
      

  13.   

           int  = 0;
            long begin = System.currentTimeMillis();
            for(int i=0;i<10000000;i++)
                for(int j=0;j<100;j++){
                    ++;
                }
            long use = System.currentTimeMillis()- begin;
            System.out.println(use);
             = 0;
            
            long begin1 = System.currentTimeMillis();
            for(int i=0;i<100;i++)
                for(int j=0;j<10000000;j++){
                    ++;
                }
            long use1 = System.currentTimeMillis()- begin1;
            System.out.println(use1);
    1453
    13291500
    13431468
    1282
    jdk1.6 三次的结果
      

  14.   

    。。java还有能量守恒定律????
      

  15.   

    这个似乎意义真不大,要看具体的环境,
    CUP的调度,,,这都很难确定的
      

  16.   

    我觉得JVM有些不确定性,所以难免误差。
    那我想问,java for循环和C for 循环高层原理一样,用C试一试,看看到底是不是两种双层for真的不同。