Wie kann ich PriorityQueue
sortieren, wonach es sortiert werden soll?
Gibt es auch einen Unterschied zwischen den Methoden offer
und add
?
quelle
Wie kann ich PriorityQueue
sortieren, wonach es sortiert werden soll?
Gibt es auch einen Unterschied zwischen den Methoden offer
und add
?
Verwenden Sie die Konstruktorüberladung, die a benötigt, Comparator<? super E> comparator
und übergeben Sie einen Komparator, der auf die für Ihre Sortierreihenfolge geeignete Weise vergleicht. Wenn Sie ein Beispiel für die Sortierung angeben, können wir einen Beispielcode zur Implementierung des Komparators bereitstellen, wenn Sie sich nicht sicher sind. (Es ist allerdings ziemlich einfach.)
Wie bereits an anderer Stelle gesagt: offer
und add
sind nur verschiedene Implementierungen von Schnittstellenmethoden. In der JDK-Quelle habe ich add
Anrufe offer
. Obwohl add
und offer
hat möglicherweise für eine anderes Verhalten im Allgemeinen aufgrund der Fähigkeit , offer
um anzuzeigen , dass der Wert nicht aufgrund von Größenbeschränkungen hinzugefügt wird, ist dieser Unterschied unerheblich in PriorityQueue
welcher unbeschränkt ist.
Hier ist ein Beispiel für eine Prioritätswarteschlange, die nach Zeichenfolgenlänge sortiert ist:
// Test.java
import java.util.Comparator;
import java.util.PriorityQueue;
public class Test {
public static void main(String[] args) {
Comparator<String> comparator = new StringLengthComparator();
PriorityQueue<String> queue = new PriorityQueue<String>(10, comparator);
queue.add("short");
queue.add("very long indeed");
queue.add("medium");
while (queue.size() != 0) {
System.out.println(queue.remove());
}
}
}
// StringLengthComparator.java
import java.util.Comparator;
public class StringLengthComparator implements Comparator<String> {
@Override
public int compare(String x, String y) {
// Assume neither string is null. Real code should
// probably be more robust
// You could also just return x.length() - y.length(),
// which would be more efficient.
if (x.length() < y.length()) {
return -1;
}
if (x.length() > y.length()) {
return 1;
}
return 0;
}
}
Hier ist die Ausgabe:
kurz
Mittel
sehr lange in der Tat
compare
Implementierung nicht einfach seinreturn x.length() - y.length()
? (Vermeidet Verzweigungsvorhersage)add()
für den Addiervorgang verwenden, dannremove()
fühlt es sich vernünftig an; Wenn ich verwendenoffer()
würde, würde ich wahrscheinlich verwendenpoll()
... aber das ist nur eine persönliche Präferenz.Java 8-Lösung
Wir können Java 8 verwenden
lambda expression
odermethod reference
in Java 8 einführen. Falls einige String-Werte in der Prioritätswarteschlange gespeichert sind (mit Kapazität 5), können wir einen Inline-Komparator (basierend auf der Länge des Strings) bereitstellen:Verwenden des Lambda-Ausdrucks
Verwenden der Methodenreferenz
Dann können wir jeden von ihnen verwenden als:
Dies wird gedruckt:
Um die Reihenfolge umzukehren (um sie in die Warteschlange mit maximaler Priorität zu ändern), ändern Sie einfach die Reihenfolge im Inline-Komparator oder verwenden Sie sie
reversed
als:Wir können auch verwenden
Collections.reverseOrder
:Wir können also sehen, dass dies
Collections.reverseOrder
überladen ist, um einen Komparator zu verwenden, der für benutzerdefinierte Objekte nützlich sein kann. Das verwendetreversed
tatsächlichCollections.reverseOrder
:quote () vs add ()
Gemäß dem Dokument
Wenn Sie eine Warteschlange mit eingeschränkter Kapazität verwenden, ist Offer () im Allgemeinen Add () vorzuziehen, wodurch ein Element möglicherweise nur durch Auslösen einer Ausnahme nicht eingefügt werden kann. Und PriorityQueue ist eine unbegrenzte Prioritätswarteschlange, die auf einem Prioritätsheap basiert.
quelle
5
dass die Startkapazität der Warteschlange angibt?Übergeben Sie es einfach
Comparator
an den Konstruktor :Der einzige Unterschied zwischen
offer
undadd
ist die Schnittstelle, zu der sie gehören.offer
gehört zuQueue<E>
, währendadd
ursprünglich in derCollection<E>
Schnittstelle gesehen wird. Abgesehen davon machen beide Methoden genau dasselbe - fügen Sie das angegebene Element in die Prioritätswarteschlange ein.quelle
von der Warteschlangen-API :
quelle
nicht anders, wie in javadoc zu erklären:
quelle
Nur um die
add()
vs-offer()
Frage zu beantworten (da die andere imo perfekt beantwortet ist und dies möglicherweise nicht der Fall ist):Laut JavaDoc in der Schnittstellenwarteschlange "fügt die Angebotsmethode nach Möglichkeit ein Element ein und gibt andernfalls false zurück. Dies unterscheidet sich von der Collection.add-Methode, bei der ein Element möglicherweise nur durch Auslösen einer nicht aktivierten Ausnahme nicht hinzugefügt werden kann. Die Angebotsmethode ist für ausgelegt Verwendung, wenn ein Fehler eher normal als außergewöhnlich ist, z. B. in Warteschlangen mit fester Kapazität (oder "begrenzten"). "
Das heißt, wenn Sie das Element hinzufügen können (was in einer PriorityQueue immer der Fall sein sollte), funktionieren sie genau gleich. Wenn Sie das Element jedoch nicht hinzufügen
offer()
können, erhalten Sie eine schöne und hübschefalse
Rendite, während Sieadd()
eine böse, nicht aktivierte Ausnahme auslösen, die Sie nicht in Ihrem Code haben möchten. Wenn das Hinzufügen von Code nicht wie vorgesehen funktioniert und / oder normalerweise überprüft wird, verwenden Sieoffer()
. Wenn das Hinzufügen nicht dazu führt, dass etwas nicht funktioniert, verwendenadd()
und behandeln Sie die resultierende Ausnahme, die gemäß den Spezifikationen der Collection-Schnittstelle ausgelöst wird .Sie werden beide auf diese Weise implementiert, um den Vertrag auf der Warteschlangenschnittstelle, die Fehler angibt
offer()
, durch Rückgabe einerfalse
( in Warteschlangen mit eingeschränkter Kapazität bevorzugten Methode ) zu erfüllen und den Vertrag auf der Sammlungsschnittstelle, die angibt,add()
immer fehlzuschlagen, indem eine Ausnahme ausgelöst wird .Wie auch immer, ich hoffe, das klärt zumindest diesen Teil der Frage.
quelle
Hier können wir einen benutzerdefinierten Komparator definieren:
Unterschied zwischen Angebot und Hinzufügungsmethode: Link
quelle
Übergeben Sie es a
Comparator
. Geben Sie anstelle von den gewünschten Typ einT
Verwenden von Lambdas (Java 8+):
Klassische Methode mit anonymer Klasse:
Um in umgekehrter Reihenfolge zu sortieren, tauschen Sie einfach e1, e2 aus.
quelle
Ich habe mich auch über die Druckreihenfolge gewundert. Betrachten Sie diesen Fall zum Beispiel:
Für eine Prioritätswarteschlange:
Dieser Code:
kann anders drucken als:
Ich habe die Antwort aus einer Diskussion in einem anderen Forum gefunden , in der ein Benutzer sagte: "Die Methode quote () / add () fügt das Element nur in die Warteschlange ein. Wenn Sie eine vorhersehbare Reihenfolge wünschen, sollten Sie peek / poll verwenden, die den Kopf zurückgeben der Warteschlange. "
quelle
Alternativ zur Verwendung
Comparator
können Sie auch die Klasse verwenden, die Sie in IhremPriorityQueue
Implementierungsprogramm verwendenComparable
(und diecompareTo
Methode entsprechend überschreiben ).Beachten Sie, dass es im Allgemeinen am besten ist, nur zu verwenden,
Comparable
anstatt,Comparator
wenn diese Reihenfolge die intuitive Reihenfolge des Objekts ist. Wenn Sie beispielsweise einen Anwendungsfall zum Sortieren vonPerson
Objekten nach Alter haben, ist es wahrscheinlich am besten,Comparator
stattdessen nur zu verwenden .Ausgabe:
quelle
Der Prioritätswarteschlange ist jedem Element eine Priorität zugewiesen. Das Element mit der höchsten Priorität wird oben in der Warteschlange angezeigt. Nun hängt es von Ihnen ab, wie jedem Element Priorität zugewiesen werden soll. Wenn Sie dies nicht tun, wird Java dies standardmäßig tun. Das Element mit dem geringsten Wert erhält die höchste Priorität und wird daher zuerst aus der Warteschlange entfernt. Wenn es mehrere Elemente mit derselben höchsten Priorität gibt, wird die Bindung willkürlich unterbrochen. Sie können eine Reihenfolge auch mit Comparator im Konstruktor angeben
PriorityQueue(initialCapacity, comparator)
Beispielcode:
Ausgabe:
Andernfalls können Sie auch einen benutzerdefinierten Komparator definieren:
quelle
Hier ist das einfache Beispiel, das Sie für das anfängliche Lernen verwenden können:
quelle