I am using JDK-8 (x64). For Arrays.sort
(primitives) I found the following in the Java documentation:
The sorting algorithm is a Dual-Pivot Quicksort by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch.`
For Collections.sort
(objects) I found this "Timsort":
This implementation is a stable, adaptive, iterative mergesort ... This implementation dumps the specified list into an array, sorts the array, and iterates over the list resetting each element from the corresponding position in the array.
If Collections.sort
uses an array, why doesn't it just call Arrays.sort
or use dual-pivot QuickSort? Why use Mergesort?
MergeSort or more specifically Timsort is used by Arrays. sort for sorting collections of objects.
Collections. sort() Operates on List Whereas Arrays. sort() Operates on an Array. Arrays.
There are certain reasons due to which quicksort is better: 1- Auxiliary Space: Quick sort is an in-place sorting algorithm. In-place sorting means no additional storage space is needed to perform sorting. Merge sort on the other hand requires a temporary array to merge the sorted arrays and hence it is not in-place.
Merge sort requires more space as it creates an extra array for storing, and no matter what it will compare every item. Quick sort on the other hand does not require extra space, and doesn't swap or compare more than necessary.
The API guarantees a stable sorting which Quicksort doesn’t offer. However, when sorting primitive values by their natural order you won’t notice a difference as primitive values have no identity. Therefore, Quicksort can used for primitive arrays and will be used when it is considered more efficient¹.
For objects you may notice, when objects with different identity which are deemed equal according to their equals
implementation or the provided Comparator
change their order. Therefore, Quicksort is not an option. So a variant of MergeSort is used, the current Java versions use TimSort. This applies to both, Arrays.sort
and Collections.sort
, though with Java 8, the List
itself may override the sort algorithms.
¹ The efficiency advantage of Quicksort is needing less memory when done in-place. But it has a dramatic worst case performance and can’t exploit runs of pre-sorted data in an array, which TimSort does.
Therefore, the sorting algorithms were reworked from version to version, while staying in the now-misleadingly named class DualPivotQuicksort
. Also, the documentation didn’t catch up, which shows, that it is a bad idea in general, to name an internally used algorithm in a specification, when not necessary.
The current situation (including Java 8 to Java 11) is as follows:
sort(char[],…)
and sort(short[],…)
add another special case, to use Counting sort for arrays whose length exceeds a certain thresholdsort(byte[],…)
will use Counting sort, but with a much smaller threshold, which creates the biggest contrast to the documentation, as sort(byte[],…)
never uses Quicksort. It only uses Insertion sort for small arrays and Counting sort otherwise.I don't know about the documentation, but the implementation of java.util.Collections#sort
in Java 8 (HotSpot) goes like this:
@SuppressWarnings({"unchecked", "rawtypes"}) public static <T> void sort(List<T> list, Comparator<? super T> c) { list.sort(c); }
And List#sort
has this implementation:
@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); } }
So, in the end, Collections#sort
uses Arrays#sort
(of object elements) behind the scenes. This implementation uses merge sort or tim sort.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With