Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 基本数组的现代for循环_Java_Performance_Arrays_Iteration - Fatal编程技术网

Java 基本数组的现代for循环

Java 基本数组的现代for循环,java,performance,arrays,iteration,Java,Performance,Arrays,Iteration,基本数组上的for循环之间是否存在性能差异 假设: double[] doubleArray = new double[300000]; for (double var: doubleArray) someComplexCalculation(var); 或: 因此,现代循环实际上运行得更快,至少在我的Mac OSX JVM 1.5上是这样 为什么不自己测量呢 这听起来有点刺耳,但这类问题很容易让你自己验证 只需创建数组并执行每个循环1000次或更多次,然后测量时间量。重复几次以消

基本数组上的for循环之间是否存在性能差异

假设:

double[] doubleArray = new double[300000];


for (double var: doubleArray) 
   someComplexCalculation(var);
或:


因此,现代循环实际上运行得更快,至少在我的Mac OSX JVM 1.5上是这样

为什么不自己测量呢

这听起来有点刺耳,但这类问题很容易让你自己验证


只需创建数组并执行每个循环1000次或更多次,然后测量时间量。重复几次以消除故障。

没有区别。Java将增强的for转换为普通的for循环。增强的for只是一个“语法糖”。两个循环生成的字节码是相同的。

我的观点是,您不知道也不应该猜测。如今,试图智胜编译器是徒劳的

有些时候,人们学习“模式”似乎可以优化某些操作,但在下一版本的Java中,这些模式实际上要慢一些

始终尽可能清楚地写出来,不要担心优化问题,直到您手中确实有一些用户规范,并且无法满足某些需求,甚至在测试之前和之后都要非常小心地运行,以确保您的“修复”实际改进了它,足以使该需求通过

编译器可以做一些令人惊讶的事情,这会让你大吃一惊,即使你做了一些在某个大范围内迭代的测试,如果你有一个较小的范围或者改变了循环中发生的事情,它的性能可能会完全不同

即时编译意味着它有时可以超越C,在某些情况下它没有理由不能超越静态汇编语言(汇编无法事先确定不需要调用,Java有时可以做到这一点)

总而言之:你能在代码中投入的最大价值就是把它写得可读。

你手写的“旧”形式执行的指令更少,而且可能更快,尽管你必须在给定的JIT编译器下对其进行分析才能确定。而“新”形式肯定不会更快

如果您查看反汇编代码(由Sun的JDK 1.5编译),您将看到“新”表单相当于以下代码:

1: double[] tmp = doubleArray;
2: for (int i = 0, y = tmp.length; i < y; i++) {
3:   double var = tmp[i];
4:   someComplexCalculation(var);
5: }
1:double[]tmp=doubleArray;
2:for(int i=0,y=tmp.length;i
因此,您可以看到使用了更多的局部变量。第1行的
doubleArray
tmp
的赋值是“额外的”,但它不会出现在循环中,并且可能无法测量。第3行的
var
赋值也是额外的。如果性能有差异,这将负责

第1行似乎没有必要,但如果数组是在进入循环之前由方法计算的,那么它就是缓存结果的样板


也就是说,我会使用新表单,除非您需要使用索引变量。任何性能差异都可能在运行时被JIT编译器优化掉,并且新表单更加清晰。如果您继续“手工”完成,您可能会错过未来的优化。通常,一个好的编译器可以优化“愚蠢”代码编写得很好,但无意中发现了“智能”代码。

我对你的问题很好奇,甚至在我之前的回答之后。所以我决定自己也检查一下。我写了这段小代码(请忽略检查数字是否为素数的数学正确性;-):

public class TestEnhancedFor{
公共静态void main(字符串参数[]){
针对()的新测试增强;
}
公共测试取消(){
int numberOfItems=100000;
double[]项=GetArrayFitems(numberOfItems);
整数重复=0;
漫长的开始,漫长的结束;
做{
start=System.currentTimeMillis();
DONOMALFOR(项目);
end=System.currentTimeMillis();
System.out.printf(“重复%d的正常值:%d\n”,
重复,结束-开始);
start=System.currentTimeMillis();
不取消(项目);
end=System.currentTimeMillis();
System.out.printf(“针对重复%d的增强:%d\n\n”,
重复,结束-开始);
}而(++重复次数<5次);
}
私人双[]GetArrayFitems(int numberOfItems){
double[]项目=新的double[numberOfItems];
对于(int i=0;i
运行应用程序为我提供了以下结果:

正常的。重复0:5594 增强的。重复0:5594

正常的。重复1:5531 增强的。重复1:5547

正常的。重复2:5532 增强的。重复2:5578

正常的。重复3:5531 增强的。重复3:5531

正常的。重复4:5547 增强的。重复4:5532

正如我们所见,结果之间的差异非常小,有时正常循环运行得更快,有时增强循环运行得更快。由于我的电脑中还有其他应用程序打开,我觉得这很正常。而且,只有第一次执行比其他执行慢——我相信这与JIT优化有关

正常环路的平均时间(不包括第一次重复)为5535,25ms,增强环路的平均时间为5547ms。但我们可以看到,对这两种情况来说,最佳运行时间
Total timeused for modern loop= 13269ms
Total timeused for old loop   = 15370ms
1: double[] tmp = doubleArray;
2: for (int i = 0, y = tmp.length; i < y; i++) {
3:   double var = tmp[i];
4:   someComplexCalculation(var);
5: }
public class TestEnhancedFor {

    public static void main(String args[]){
        new TestEnhancedFor();
    }

    public TestEnhancedFor(){
        int numberOfItems = 100000;
        double[] items = getArrayOfItems(numberOfItems);
        int repetitions = 0;
        long start, end;

        do {
            start = System.currentTimeMillis();
            doNormalFor(items);
            end = System.currentTimeMillis();
            System.out.printf("Normal For. Repetition %d: %d\n", 
                    repetitions, end-start);

            start = System.currentTimeMillis();
            doEnhancedFor(items);
            end = System.currentTimeMillis();
            System.out.printf("Enhanced For. Repetition %d: %d\n\n", 
                    repetitions, end-start);

        } while (++repetitions < 5);
    }

    private double[] getArrayOfItems(int numberOfItems){
        double[] items = new double[numberOfItems];
        for (int i=0; i < numberOfItems; i++)
            items[i] = i;
        return items;
    }

    private void doSomeComplexCalculation(double item){
        // check if item is prime number
        for (int i = 3; i < item / 2; i+=2){
            if ((item / i) == (int) (item / i)) break;
        }
    }

    private void doNormalFor(double[] items){
        for (int i = 0; i < items.length; i++)
            doSomeComplexCalculation(items[i]);
    }

    private void doEnhancedFor(double[] items){
        for (double item : items)
            doSomeComplexCalculation(item);
    }

}