在原始类型的Java Arrays.sort()中使用快速排序。另一方面,对象的Arrays.sort()使用Merge排序。同样适用于Collection.sort(),它也使用Merge排序。集合排序使用下面的Arrays排序实现。所以,简单来说,我可以说基元是使用快速排序排序的,但是对象是使用合并排序进行排序的。
我的猜测是它与自己的排序算法有关。关于快速排序与合并排序的SO有很多讨论,例如this和this。似乎存在相互冲突的主张哪个更好,这是可以理解的,因为这取决于数据集。
我的理解是
Android API似乎遵循与Java相同的模式。这是我在Arrays.java
中找到的 public static void sort(long[] array) {
DualPivotQuicksort.sort(array);
}
而且,
public static void sort(Object[] array) {
ComparableTimSort.sort(array);
}
我不明白的是,是什么让Merge排序成为在Java或Android中排序对象的好选择?为什么不把这个决定留给开发者?
答案 0 :(得分:7)
关键问题是排序稳定性 - 如果从排序顺序的角度看两个元素相等,它们是否会以与输入中相同的顺序出现在结果中。
对于例如long
。输入中3
的所有实例都将组合在一起,没有人关心哪个实例。
另一方面,对象可能以不影响排序顺序的方式不同。如果您按腿数分类动物,您可能会关心“猫”和“狗”是否保持原始顺序。
Arrays.sort mergesort稳定。用于基元的快速排序不需要稳定。
答案 1 :(得分:2)
请参阅此答案:Why Collections.sort uses merge sort instead of quicksort?
TL; DR:
与mergesort相比,QuickSort有两个主要缺陷:
- 它不稳定(正如parsifal所说)。
- 它不能保证n log n的性能;它可以降低到病理输入的二次性能。
醇>
答案 2 :(得分:2)
我认为
的问题是什么使合并排序成为排序Java对象的良好候选者 对原语进行快速排序?
已被其他人回答,但问题是
为什么这个决定还没有留给开发人员?
尚未得到解决。
事实上,任何开发人员都可以轻松地从Collection
或ArrayList
和 隐藏 sort()
方法派生新类(由于sort()
是static
方法,因此必须 hidden, not overidden )并使用自己的自定义实现。
这很少(如果有的话)完成的事实可能是因为今天的大多数年轻程序员比C ++更多地接触Java。在Java社区中,"抽象"这意味着你不知道一个类的底层实现是如何工作的,而且你不需要。 JVM的机器独立性使我们对速度/效率权衡的直觉变得愚蠢。因此,我们中的许多人对数据结构和算法的理解并不像一些较老的,经验丰富的程序员那样清晰。
这几乎与对C ++中抽象的理解相反。引用Alex Stepanov:
事实上,我不相信图书馆可以消除 程序员需要了解算法和数据结构。它 只是消除了程序员实现它们的需要。一个需要 了解要使用的数据结构的基本属性 它们适当地使应用程序满足其自身的复杂性 要求。
答案 3 :(得分:1)
合并排序是稳定的:由于排序
,不会重新排序相等的元素