为什么Java的Arrays.sort方法对不同types使用两种不同的sortingalgorithm?

Java的Arrays.sort方法使用Quicksort处理基元数组,并为对象数组合并sorting。 我相信大部分时间Quicksort比合并sorting更快并且成本更低。 我的实验支持,尽pipe这两种algorithm都是O(n log(n))。 那么为什么不同的algorithm用于不同的types呢?

最可能的原因是:快速sorting不稳定 ,即在sorting时,相同的条目可以改变它们的相对位置; 除此之外,这意味着如果你sorting已经sorting的数组,它可能不会保持不变。

由于原始types没有标识(没有办法区分具有相同值的两个整数),这对他们来说并不重要。 但对于参考types,它可能会导致一些应用程序的问题。 因此,对这些使用稳定的合并sorting。

OTOH,原因不使用(保证n * log(n))合并sorting原始types的原因可能是它需要对数组进行克隆。 对于引用types来说,引用的对象通常比引用数组占用的内存要多得多,这通常并不重要。 但是对于原始types,彻底克隆该arrays会使内存使用量翻番。

根据此答案中引用的Java 7 API文档,对象数组的Arrays#Sort()现在使用TimSort ,它是MergeSort和InsertionSort的混合。 另一方面,原始数组的Arrays#sort()现在使用Dual-Pivot QuickSort 。 这些更改从Java SE 7开始实施。

我能想到的一个原因是,quicksort的最坏情况时间复杂度为O( n ^ 2 ),而mergesort保留最坏情况时间O( n log n )。 对于对象数组,有一个公平的期望,会有多个重复的对象引用,这是快速sorting最差的一种情况。

对各种algorithm有一个体面的视觉比较 ,要特别注意不同algorithm的最右图。

我正在参加Coursera的algorithm课程,并且在其中一个讲座教授Bob Sedgewick提到了Java系统的评估:

“如果一个程序员正在使用对象,空间可能不是一个非常重要的考虑因素,合并sorting所使用的额外空间可能不是一个问题,而如果一个程序员使用原始types,性能可能是最重要的,快速sorting“。