标题参考“为什么处理排序数组比未排序数组快?
这也是分支预测的效果吗?当心:这里排序数组的处理速度较慢!
考虑以下代码:
private static final int LIST_LENGTH = 1000 * 1000;
private static final long SLOW_ITERATION_MILLIS = 1000L * 10L;
@Test
public void testBinarySearch() {
    Random r = new Random(0);
    List<Double> list = new ArrayList<>(LIST_LENGTH);
    for (int i = 0; i < LIST_LENGTH; i++) {
        list.add(r.nextDouble());
    }
    //Collections.sort(list);
    // remove possible artifacts due to the sorting call
    // and rebuild the list from scratch:
    list = new ArrayList<>(list);
    int nIterations = 0;
    long startTime = System.currentTimeMillis();
    do {
        int index = r.nextInt(LIST_LENGTH);
        assertEquals(index, list.indexOf(list.get(index)));
        nIterations++;
    } while (System.currentTimeMillis() < startTime + SLOW_ITERATION_MILLIS);
    long duration = System.currentTimeMillis() - startTime;
    double slowFindsPerSec = (double) nIterations / duration * 1000;
    System.out.println(slowFindsPerSec);
    ...
}
这将在我的机器上打印出大约720的值。
现在,如果我激活了集合排序调用,该值将下降到142。为什么?!?
结果是结论性的,如果我增加每次迭代的次数,它们不会改变。
Java版本是1.8.0_71(Oracle VM,64位),在Windows 10下运行,在Eclipse Mars中进行了JUnit测试。
更新
似乎与连续的内存访问有关(按顺序与随机顺序访问Double对象)。对于大约10k或更短的数组长度,该效果对我而言已消失。
感谢assylias提供的结果:
/**
 * Benchmark                     Mode  Cnt  Score   Error  Units
 * SO35018999.shuffled           avgt   10  8.895 ± 1.534  ms/op
 * SO35018999.sorted             avgt   10  8.093 ± 3.093  ms/op
 * SO35018999.sorted_contiguous  avgt   10  1.665 ± 0.397  ms/op
 * SO35018999.unsorted           avgt   10  2.700 ± 0.302  ms/op
 */