Ich verwende JDK-8 (x64). Für Arrays.sort
(Grundelemente) habe ich in der Java-Dokumentation Folgendes gefunden:
Der Sortieralgorithmus ist ein Dual-Pivot- Quicksort von Vladimir Yaroslavskiy, Jon Bentley und Joshua Bloch. "
Für Collections.sort
(Objekte) habe ich dieses "Timsort" gefunden:
Diese Implementierung ist eine stabile, adaptive, iterative Zusammenführung ... Diese Implementierung speichert die angegebene Liste in einem Array, sortiert das Array und iteriert über die Liste, wobei jedes Element von der entsprechenden Position im Array zurückgesetzt wird.
Wenn Collections.sort
ein Array verwendet wird, warum wird dann nicht einfach QuickSortArrays.sort
mit zwei Pivots aufgerufen oder verwendet ? Warum Mergesort verwenden ?
Antworten:
Die API garantiert eine stabile Sortierung, die Quicksort nicht bietet. Wenn Sie jedoch primitive Werte nach ihrer natürlichen Reihenfolge sortieren, werden Sie keinen Unterschied bemerken, da primitive Werte keine Identität haben. Daher kann Quicksort für primitive Arrays verwendet werden und wird verwendet, wenn es als effizienter angesehen wird¹.
Bei Objekten können Sie feststellen, dass Objekte mit unterschiedlicher Identität, die je nach
equals
Implementierung oder Bereitstellung als gleich angesehen werden,Comparator
ihre Reihenfolge ändern. Daher ist Quicksort keine Option. Daher wird eine Variante von MergeSort verwendet, die aktuellen Java-Versionen verwenden TimSort . Dies gilt für beide,Arrays.sort
undCollections.sort
obwohl mit Java 8List
selbst die Sortieralgorithmen überschrieben werden können.¹ Der Effizienzvorteil von Quicksort besteht darin, dass an Ort und Stelle weniger Speicher benötigt wird. Es hat jedoch eine dramatische Worst-Case-Leistung und kann keine Läufe vorsortierter Daten in einem Array ausnutzen, wie dies TimSort tut.
Daher wurden die Sortieralgorithmen von Version zu Version überarbeitet, während sie in der jetzt irreführend benannten Klasse blieben
DualPivotQuicksort
. Außerdem hat die Dokumentation nicht aufgeholt, was zeigt, dass es im Allgemeinen eine schlechte Idee ist, einen intern verwendeten Algorithmus in einer Spezifikation zu benennen, wenn dies nicht erforderlich ist.Die aktuelle Situation (einschließlich Java 8 bis Java 11) ist wie folgt:
sort(char[],…)
undsort(short[],…)
fügen Sie einen weiteren Sonderfall hinzu, um die Zählsortierung für Arrays zu verwenden, deren Länge einen bestimmten Schwellenwert überschreitetsort(byte[],…)
wird die Zählsortierung verwendet , jedoch mit einem viel kleineren Schwellenwert, der den größten Kontrast zur Dokumentation bildet, dasort(byte[],…)
Quicksort niemals verwendet wird. Es wird nur die Einfügesortierung für kleine Arrays und die Zählsortierung verwendet .quelle
List.sort
Methode implementieren .Collections.sort
könnte niemals garantieren, dass die korrekte Arbeitsweise für jedeList
Implementierung korrekt ist, da sie nicht garantieren kann, z. B. dass derList
Inhalt nicht fälschlicherweise geändert wird. Alles läuft darauf hinaus, dass die Garantie vonCollections.sort
nur für korrekteList
Implementierungen (und korrekteComparator
oderequals
Implementierungen) gilt.Collections.sort
die delegiert wirdList.sort
.Collections.sort
erwähnt nicht einmal in seiner Typensignatur, dass die Ausgabe sortiert ist?Collections.sort
wäre der Rückgabetyp so etwas wie "eine Sammlung des gleichen Typs und der gleichen Länge wie die Eingabe mit den Eigenschaften, dass 1) jedes in der Eingabe vorhandene Element auch in der Ausgabe vorhanden ist, 2 ) für jedes Elementpaar aus der Ausgabe ist das linke nicht größer als das rechte, 3) für jedes Paar gleicher Elemente aus der Ausgabe ist der linke Index in der Eingabe kleiner als der rechte "oder so ähnlich Das.Ich weiß nichts über die Dokumentation, aber die Implementierung
java.util.Collections#sort
in Java 8 (HotSpot) sieht folgendermaßen aus:Und
List#sort
hat diese Implementierung:Collections#sort
Verwendet also am EndeArrays#sort
(von Objektelementen) hinter den Kulissen. Diese Implementierung verwendet Merge Sort oder Tim Sort.quelle
Laut Javadoc werden nur primitive Arrays mit Quicksort sortiert. Objektarrays werden ebenfalls mit einem Mergesort sortiert.
Collections.sort scheint also denselben Sortieralgorithmus wie Arrays.sort für Objekte zu verwenden.
Eine andere Frage wäre, warum für primitive Arrays ein anderer Sortieralgorithmus verwendet wird als für Objekt-Arrays.
quelle
Wie in vielen Antworten angegeben.
Das Quicksort wird von Arrays.sort zum Sortieren primitiver Sammlungen verwendet, da keine Stabilität erforderlich ist (Sie wissen nicht, ob zwei identische Ints in der Sortierung ausgetauscht wurden).
MergeSort oder genauer gesagt Timsort wird von Arrays.sort zum Sortieren von Sammlungen von Objekten verwendet. Stabilität ist erforderlich. Quicksort sorgt nicht für Stabilität, Timsort schon.
Collections.sort delegiert an Arrays.sort, weshalb das Javadoc auf MergeSort verweist.
quelle
Die schnelle Sortierung hat zwei Hauptnachteile beim Zusammenführen der Sortierung:
Stabilität ist für primitive Typen kein Thema, da es keinen Begriff von Identität gibt, der sich von (Wert-) Gleichheit unterscheidet.
Stabilität ist eine große Sache beim Sortieren beliebiger Objekte. Es ist ein netter Nebeneffekt, dass Merge Sort unabhängig von der Eingabe eine Leistung von n log n (Zeit) garantiert. Aus diesem Grund wird die Zusammenführungssortierung ausgewählt, um eine stabile Sortierung (Zusammenführungssortierung) zum Sortieren von Objektreferenzen bereitzustellen.
quelle