为什么在Java 1.8中进行此类排序

Dan*_*cio 4 java arrays sorting timsort

取自Joshua Bloch和Neal Gafter的Java Puzzlers

import java.util.*;

public class BananaBread {
    public static void main(String[] args) {
        Integer[] array = { 3, 1, 4, 1, 5, 9 };
        Arrays.sort(array, new Comparator<Integer>() {
            public int compare(Integer i1, Integer i2) {
                return i1 < i2 ? -1 : (i2 > i1 ? 1 : 0);
            }
        });
        System.out.println(Arrays.toString(array));
    }
}
Run Code Online (Sandbox Code Playgroud)

预期的行为是未定义的,文本说它返回[3,1,4,1,5,9].这适用于Java V1.7.但是,在Java v.1.8中,输出是排序列表.

我可以看到Timsort是Java 1.8中的新功能,但我不确定算法如何使用不一致的比较器(例如上面给出的)来运行.任何有关如何做到这一点的帮助或见解将不胜感激.

Pet*_*rey 7

Java 8使用修改的合并排序.它使用的关键是

// From TimSort.binarySort
while (left < right) {
    int mid = (left + right) >>> 1;
    if (c.compare(pivot, a[mid]) < 0)  // compares for less than 0.
        right = mid;
    else
        left = mid + 1;
}
Run Code Online (Sandbox Code Playgroud)

注意:它只关心你是返回-1还是0(更具体地说是<0,true或false)

你的比较器与

return i1 < i2 ? -1 : 0;
Run Code Online (Sandbox Code Playgroud)

所以在这个代码的所有重要方面都是正确的.

注意:如果您更改此代码

return i1 > i2 ? +1 : 0;
Run Code Online (Sandbox Code Playgroud)

它没有任何排序.

  • 如果您使用VM arg` -Djava.util.Arrays.useLegacyMergeSort = true`,您可以获得原始合并排序.有人懒洋洋地将我们的比较器编码为-1和0,我花了很长时间才弄清楚当我们迁移到JDK8时它停止排序的原因. (2认同)