为什么Collections.sort使用Mergesort但Arrays.sort不?

我正在使用JDK-8(x64)。 对于Arrays.sort我在Java文档中find了以下内容:

sortingalgorithm是由Vladimir Yaroslavskiy,Jon Bentley和Joshua Bloch提供的Dual-Pivot Quicksort

对于Collections.sort我发现这个:

这个实现是一个稳定的,自适应的,迭代的mergesort …这个实现把指定的列表转储到一个数组中,对数组进行sorting ,然后对列表进行迭代,以重置数组中相应位置的每个元素。

如果Collections.sort使用数组,为什么不调用Arrays.sort或使用双枢轴QuickSort ? 为什么使用Mergesort

API保证Quicksort不提供稳定的sorting。 但是,当按照自然顺序对原始值进行sorting时,由于原始值没有标识,因此不会注意到差异。 因此,Quicksort用于原始数组,因为它稍微有效一些。

对于您可能会注意到的对象,根据等式实现或提供的Comparator器视为相同的对象更改其顺序时。 因此,Quicksort不是一个选项。 所以使用MergeSort的一个变体,当前的Java版本使用TimSort 。 这适用于Arrays.sortCollections.sort ,但对于Java 8, List本身可能会覆盖sortingalgorithm。

我不知道文档,但Java 8(HotSpot)中的java.util.Collections#sort的实现如下所示:

 @SuppressWarnings({"unchecked", "rawtypes"}) public static <T> void sort(List<T> list, Comparator<? super T> c) { list.sort(c); } 

List#sort有这个实现:

 @SuppressWarnings({"unchecked", "rawtypes"}) default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } } 

所以最后, Collections#sort在后台使用Arrays#sort (对象元素)。 此实现使用合并sorting或timsorting。

根据Javadoc,只有原始数组使用Quicksortsorting。 对象数组也使用Mergesort进行sorting。

所以Collections.sort似乎使用与Arrays.sort对象相同的sortingalgorithm。

另一个问题是为什么一个不同的sortingalgorithm用于原始数组而不是对象数组?

正如许多答案中所述。

Arrays.sort使用Quicksort来对原始集合进行sorting,因为不需要稳定性(您不会知道或关心两个相同的整数是否在sorting中交换)

MergeSort或更具体地说,Timsort被Arrays.sort用来sorting对象的集合。 稳定性是必需的。 Timsort确实没有提供Quicksort的稳定性。

Collections.sort委托给Arrays.sort,这就是您看到引用MergeSort的javadoc的原因。

对于合并sorting,Quick Sort有两个主要缺点:

  • 它不是非稳定的,而是非原始的。
  • 它不保证n日志性能。

对于原始types来说,稳定性不是问题,因为没有认同(value)相等的概念。

sorting任意对象时,稳定性是一件大事。 无论input什么,合并sorting都能保证n日志(时间)性能,这是一个很好的优势。 这就是为什么select合并sorting来提供稳定的sorting(合并sorting)来sorting对象引用。