哪个循环更有效?

时间:2019-07-06 12:18:45

标签: java loops logic

我想知道哪个代码更有效,我有两个选择。您会说哪个更有效?为什么?谢谢。

选项A

array1 size is 1000
array2 size is 2000

for(int i = 0; i < array1.size(); i++)
{
    for(int j = 0; j < array2.size(); j++) {
        if(array1[i].method() == array2[j].method()) // CHECKS IF THERE'S AN EQUAL IN BOTH ARRAYS
        {
            doSomething();
            break;
        }
        if(j == array2.size()-1) // CHECKS IF ARRAY1 DID NOT FIND A MATCH
        {
            doSomething();
            break;
        }
        for(k = 0; k < array1.size(); k++)
        {
            if(array1[k].method() == array2[j].method()) // CHECKS IF THERE'S AN EQUAL IN BOTH ARRAYS
            {
                // BUT DOES NOTHING BECAUSE IT WAS DONE ALREADY UPSIDE
                break;
            }
            if(k == array1.size()-1) // CHECKS IF ARRAY2 DID NOT FIND A MATCH
            {
                doSomething();
                break;
            }
        }
    }
}

选项B

array1 size is 1000
array2 size is 2000


    for(int i = 0; i < array1.size(); i++)
    {
        for(int j = 0; j < array2.size(); j++) {
            if(array1[i].method() == array2[j].method()) // CHECKS IF THERE'S AN EQUAL IN BOTH ARRAYS
            {
                doSomething();
                break;
            }
            if(j == array2.size-1)  // CHECKS IF ARRAY1 HAS NO ARRAY2 MATCH
            {
                doSomething();
                break;
            }
        }
    }

    for(int j = 0; j < array2.size(); j++)
    {
        for(int i = 0; i < array1.size(); i++) {
            if(array2[j].method() == array1[i].method()) // CHECKS IF THERE'S AN EQUAL IN BOTH ARRAYS
            {
                // BUT DOES NOTHING BECAUSE IT WAS DONE ALREADY UPSIDE
                break;
            }
            if(i == array1.size-1) // CHECKS IF ARRAY2 HAS NO ARRAY1 MATCH
            {
                doSomething();
                break;
            }
        }
    }

我目前已经实现了OPTION B,我想知道是否应该转移到OPTION A,因为尽管Option A可能花费更多时间,但我不知道同时执行两个循环还是一次执行所有迭代是否会花费更多时间。 也许是一样的,我不太了解。

3 个答案:

答案 0 :(得分:1)

选项A 为O(x ^ 2 * y) 选项B 为O(x * y) 在您的情况下,选项A最多进行2,000,000,000次迭代,而选项B最多进行4,000,000次迭代。当然,这不包括休息或继续。我可能会坚持使用B。

答案 1 :(得分:1)

正如@ Sploder12所说的那样,但是在循环中删除函数调用也可以带来很多好处,例如

int n= array.size()
for(int i=0; i<n; i++)

而不是

 for(int i=0; i<array.size(); i++)

除非您要在循环中修改数组大小,否则重复的函数调用是一种浪费。

答案 2 :(得分:0)

关于@ Turing85的评论,我确实想知道是否有某种编译器机制可以发现以下事实:循环初始化中size()的返回值可能是常量,因此可以用常量“有效地最终”。因此,我运行了以下两个循环,第一个没有手动进行持续优化:

int n1=a1.size();
for(int i=0; i<a1.size(); i++) {
    int n2=a2.size();
    for(int j=0; j<a2.size(); j++) {
        int n3=a3.size();
        for(int k=0; k<a3.size(); k++) {
            int candidate=a1.get(i)*a2.get(j)*a3.get(k);
            candidate+=n1*n2*n3;
            func(candidate);
        }//k
    }//j
}//i

第二个手动不断优化:

int n1=a1.size();
for(int i=0; i<n1; i++) {
    int n2=a2.size();
    for(int j=0; j<n2; j++) {
        int n3=a3.size();
        for(int k=0; k<n3; k++) {
            int candidate=a1.get(i)*a2.get(j)*a3.get(k);
            candidate+=n1*n2*n3;
            func(candidate);
        }//k
    }//j
}//i

然后我使用a1.size()= 100,a2.size()= 200和a3.size()= 300运行这些循环10次以获取时间,并计算出100次均值和标准误差循环的每个变化(以200为顺序)随机进行。

在单个作业(即JVM的一次调用)中,整个过程重复了10次,以获得10个成对的均值和标准错误(该对中的一个成员来自优化的运行,另一个来自未优化的运行)。在所有10种情况下,优化的平均时间都比未优化的平均时间快得多。在每种情况下,均值之间的差异均大于标准误差的6.9倍,而在10种情况中,有7种均值之间的差异均大于15个标准误差。数据如下。为循环生成的字节码是不同的,尽管我不声称要讲字节码,但还存在对a * .size()的附加invokevirtual调用,我认为这是造成两个循环版本性能差异的原因。

因此,考虑到@ Turing85的评论,我想知道在什么条件下可以忽略“在此级别上”的优化吗?

openjdk版本“ 11” 2018-09-25 OpenJDK运行时环境18.9(内部版本11 + 28) OpenJDK 64位服务器VM 18.9(内部版本11 + 28,混合模式)

======数据======

100次优化循环的平均时间为6.412s,标准误为0.013; 100次未优化的循环平均运行6.502秒,标准误为0.013

100次优化循环的平均时间为5.143s,标准误为0.004; 100次未优化的循环平均运行5.232s,标准误为0.005

100次优化循环平均耗时6.090s,标准误为0.006; 100次未优化的循环平均运行6.175秒,标准误为0.006

100次优化循环平均每次需要5.739s,标准误为0.005; 100次未优化的循环平均每次运行5.827s,标准误为0.005

100次优化循环平均每次运行5.613s,标准误为0.005; 100次未优化的循环平均每次运行5.697s,标准误为0.004

100次优化循环的平均每次运行6.045s,标准误为0.004; 100次未优化的循环平均运行6.121秒,标准误为0.004

100次优化循环的平均时间为5.333s,标准误为0.003; 100次未优化的循环平均运行5.415秒,标准误为0.003

100次优化循环的平均每次运行时间为5.903s,标准误为0.009; 100次未优化的循环平均每次运行5.972s,标准误为0.007

100次优化循环的平均时间为5.770s,标准误为0.005; 100次未优化的循环平均运行5.851秒,标准误为0.005

100次优化循环的平均时间为4.975s,标准误为0.004; 100次未优化的循环平均运行5.052秒,标准误为0.004