Java 基本的插入排序优化使代码速度变慢

Java 基本的插入排序优化使代码速度变慢,java,algorithm,sorting,insertion-sort,Java,Algorithm,Sorting,Insertion Sort,明天我要教一个关于插入排序的演示。一个重要的优化是在内部循环中添加一个检查,一旦您将一个项目放入正确的位置,该检查将阻止它迭代。所以基本上是这样的: public static void insertionSort(int[] array) { for (int i = 0; i < array.length; i++) { for (int j = i; j > 0; j--) { if (array[j] < array[j-

明天我要教一个关于插入排序的演示。一个重要的优化是在内部循环中添加一个检查,一旦您将一个项目放入正确的位置,该检查将阻止它迭代。所以基本上是这样的:

public static void insertionSort(int[] array) {
    for (int i = 0; i < array.length; i++) {
        for (int j = i; j > 0; j--) {
            if (array[j] < array[j-1]) {
                int tmp = array[j];
                array[j] = array[j-1];
                array[j-1] = tmp;
            }
        }
    }
}
公共静态void insertionSort(int[]数组){
for(int i=0;i0;j--){
if(数组[j]<数组[j-1]){
int tmp=数组[j];
数组[j]=数组[j-1];
阵列[j-1]=tmp;
}
}
}
}
为此:

public static void insertionSort(int[] array) {
    for (int i = 0; i < array.length; i++) {
        for (int j = i; j > 0 && array[j] < array[j-1]; j--) {
            int tmp = array[j];
            array[j] = array[j-1];
            array[j-1] = tmp;
        }
    }
}
公共静态void insertionSort(int[]数组){
for(int i=0;i0&&array[j]
第二个版本应该更有效。然而,当我对它进行基准测试时,我实际上是在衡量第一个版本的性能,因为它的速度更快。我找不到窃听器。知道发生了什么事吗

下面是我用来进行基准测试的代码:

import java.util.Arrays;
import java.util.Random;

public class InsertionSort {
    public static void main(String[] args) {
        int[] stuff = getRandomArray(50000);
        //System.out.println(Arrays.toString(stuff));

        long started = System.currentTimeMillis();
        insertionSort(stuff);
        long finished = System.currentTimeMillis();
        long totalTime = finished - started;

        //System.out.println(Arrays.toString(stuff));

        System.out.println("Started: " + started);
        System.out.println("Finished: " + finished);
        System.out.println("Elapsed: " + totalTime);
    }

    public static int[] getRandomArray(int size) {
        int[] array = new int[size];
        Random r = new Random();
        for (int i = 0; i < array.length; i++) {
            array[i] = r.nextInt(size);
        }
        return array;
    }

    public static void insertionSort(int[] array) {
        // Implementation goes here
    }
}
导入java.util.array;
导入java.util.Random;
公共类InsertionSort{
公共静态void main(字符串[]args){
int[]stuff=getRandomArray(50000);
//System.out.println(array.toString(stuff));
长启动=System.currentTimeMillis();
插入排序(填充);
long finished=System.currentTimeMillis();
长总时间=完成-开始;
//System.out.println(array.toString(stuff));
System.out.println(“已启动:+已启动”);
System.out.println(“完成:+完成”);
System.out.println(“已用时间:+总时间”);
}
公共静态int[]getRandomArray(int大小){
int[]数组=新的int[size];
随机r=新随机();
for(int i=0;i

编辑:更改了测试数组中的项目数,并注释掉要打印的行

首先,您编写了一个所谓的微基准。你的结果没有意义,因为你没有热身阶段。这对于让JVM热点编译器执行其运行时优化至关重要

搜索“java微基准”以查找一些工具。例如


如果您的结果有意义,我想在第二个示例中,HotSpot编译器的循环优化不如第一个示例中的有效。

您的速度有多慢?在第二个版本中有一个额外的比较,您的数组没有那么长,让我编辑一下。我注意到,当接近50000个项目时,第二个版本大约1200毫秒,第一个版本大约1000毫秒,非常一致。不是很大,但我希望第一个接近N^2计算,而后者接近N^2/2。第二个算法实际上应该有较少的比较,因为第一个算法的if语句中的比较被移动到第二个算法中for循环的条件中。这会导致循环更快停止。这很奇怪。使用您提供的代码,我在OpenJDK 8上获得了大约2400ms的第一个版本和大约780ms的第二个版本…JVM选项会影响基准测试结果,如果有任何特定的选项,您可以共享它。谢谢!这对我来说是一个正确的答案。因为这是在一个非常入门的课程中作为一个例子使用的,所以我对引入特殊工具有点犹豫。然而,我发现,如果我添加一个循环来重新运行同一个测试几次,后一个结果比前一个快得多。所以我将在演示中这样做,这将给我一个很好的机会来讨论正在发生的事情,并且后面的运行更有意义。