Jak uzyskać PriorityQueue
sortowanie według tego, na czym chcę sortować?
źródło
Jak uzyskać PriorityQueue
sortowanie według tego, na czym chcę sortować?
Użyj przeciążenia konstruktora, które pobiera Comparator<? super E> comparator
i przekazuje komparator, który porównuje w odpowiedni sposób dla twojej kolejności sortowania. Jeśli podasz przykładowy sposób sortowania, możemy podać przykładowy kod do implementacji komparatora, jeśli nie jesteś pewien. (Jest to jednak dość proste.)
Jak już zostało powiedziane w innym miejscu: offer
i add
są po prostu różne implementacje metody interfejsu. W źródle JDK, które mam, add
połączenia offer
. Chociaż add
i ogólnie offer
mają potencjalnie różne zachowanie ze względu na możliwość offer
wskazania, że wartości nie można dodać z powodu ograniczeń wielkości, różnica ta nie ma znaczenia, dla PriorityQueue
której nie ma ograniczeń.
Oto przykład sortowania kolejki priorytetowej według długości łańcucha:
// 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;
}
}
Oto wynik:
krótki
średni
naprawdę bardzo długo
compare
wdrożenie nie powinno być po prostureturn x.length() - y.length()
? (Unikanie przewidywania gałęzi)add()
operacji dodawania, toremove()
jest sensowne; gdybym używałoffer()
, prawdopodobnie użyłbympoll()
... ale to tylko osobiste preferencje.Rozwiązanie Java 8
Możemy używać
lambda expression
lubmethod reference
wprowadzać w Javie 8. W przypadku, gdy mamy pewne wartości String zapisane w kolejce priorytetowej (o pojemności 5), możemy zapewnić wbudowany komparator (na podstawie długości String):Korzystanie z wyrażenia lambda
Za pomocą odwołania do metody
Następnie możemy użyć dowolnego z nich jako:
Spowoduje to wydrukowanie:
Aby odwrócić kolejność (aby zmienić na kolejkę o najwyższym priorytecie), wystarczy zmienić kolejność w komparatorze wbudowanym lub użyć
reversed
jako:Możemy również użyć
Collections.reverseOrder
:Widzimy więc, że
Collections.reverseOrder
jest przeciążony, aby wziąć komparator, który może być przydatny dla obiektów niestandardowych. Tereversed
rzeczywiście wykorzystujeCollections.reverseOrder
:offer () vs add ()
Zgodnie z dok
W przypadku korzystania z kolejki o ograniczonej pojemności opcja () jest na ogół lepsza niż metoda add (), która może nie wstawić elementu tylko przez zgłoszenie wyjątku. A PriorityQueue to nieograniczona kolejka priorytetowa oparta na stercie priorytetów.
źródło
5
wskazuje początkową pojemność kolejki?Wystarczy zaliczyć odpowiednie
Comparator
do konstruktora :Jedyną różnicą między
offer
iadd
jest interfejs, do którego należą.offer
należy doQueue<E>
, podczas gdyadd
pierwotnie jest widoczny wCollection<E>
interfejsie. Poza tym obie metody robią dokładnie to samo - wstawiają określony element do kolejki priorytetowej.źródło
z interfejsu API kolejki :
źródło
nie inaczej, jak deklarują w javadoc:
źródło
Wystarczy odpowiedzieć na pytanie
add()
vsoffer()
(ponieważ na drugie pytanie jest doskonale udzielone imo, a może nie być):Według JavaDoc w interfejsie kolejki : „Metoda oferty wstawia element, jeśli to możliwe, w przeciwnym razie zwraca false. Różni się to od metody Collection.add, która może nie dodać elementu tylko przez zgłoszenie niesprawdzonego wyjątku. Metoda oferty jest przeznaczona dla używaj, gdy awaria jest zjawiskiem normalnym, a nie wyjątkowym, na przykład w kolejkach o stałej pojemności (lub „ograniczonej”). ”
Oznacza to, że jeśli możesz dodać element (co powinno zawsze mieć miejsce w przypadku PriorityQueue), działają one dokładnie tak samo. Ale jeśli nie możesz dodać elementu,
offer()
da ci ładny i ładnyfalse
zwrot, aadd()
zgłasza nieprzyjemny wyjątek, którego nie chcesz w swoim kodzie. Jeśli brak dodania oznacza, że kod działa zgodnie z przeznaczeniem i / lub sprawdzasz go normalnie, użyjoffer()
. Jeśli brak dodawania oznacza, że coś jest zepsute, użyjadd()
i obsłuż wynikowy wyjątek zgłoszony zgodnie ze specyfikacjami interfejsu kolekcji .Oba są zaimplementowane w ten sposób, aby wypełnić kontrakt na interfejsie kolejki, który określa
offer()
awarie poprzez zwróceniefalse
( metoda preferowana w kolejkach o ograniczonej pojemności ), a także utrzymać kontrakt na interfejsie kolekcji, który określa,add()
że zawsze kończy się niepowodzeniem przez zgłoszenie wyjątku .W każdym razie, mam nadzieję, że wyjaśni to przynajmniej tę część pytania.
źródło
Tutaj możemy zdefiniować komparator zdefiniowany przez użytkownika:
Różnica między ofertą a metodami dodawania: link
źródło
Podaj to
Comparator
. Wpisz żądany typ zamiastT
Korzystanie z lambdas (Java 8+):
Klasyczny sposób, z wykorzystaniem anonimowej klasy:
Aby posortować w odwrotnej kolejności, po prostu zamień e1, e2.
źródło
Zastanawiałem się także nad kolejnością drukowania. Rozważ ten przypadek, na przykład:
W przypadku kolejki priorytetowej:
Ten kod:
może drukować inaczej niż:
Znalazłem odpowiedź z dyskusji na innym forum , na której użytkownik powiedział: „metody offer () / add () wstawiają tylko element do kolejki. Jeśli chcesz przewidzieć kolejność, powinieneś użyć peek / poll, które zwracają głowę w kolejce. ”
źródło
Alternatywą dla użycia
Comparator
może być także klasa, której używasz w swoimPriorityQueue
narzędziuComparable
(i odpowiednio przesłonićcompareTo
metodę).Zauważ, że generalnie najlepiej jest używać
Comparable
zamiast tego,Comparator
jeśli porządkowanie jest intuicyjne porządkowanie obiektu - jeśli na przykład masz przypadek użycia do sortowaniaPerson
obiektów według wieku, prawdopodobnie najlepiej po prostu użyćComparator
zamiast tego.Wynik:
źródło
Kolejka priorytetowa ma pewien priorytet przypisany do każdego elementu. Element o najwyższym priorytecie pojawia się na początku kolejki. Teraz zależy od Ciebie, w jaki sposób chcesz przypisać priorytet każdemu z elementów. Jeśli tego nie zrobisz, Java zrobi to domyślnie. Element o najmniejszej wartości ma najwyższy priorytet i dlatego jest najpierw usuwany z kolejki. Jeśli jest kilka elementów o tym samym najwyższym priorytecie, remis zostaje zerwany arbitralnie. Możesz także określić kolejność za pomocą Komparatora w konstruktorze
PriorityQueue(initialCapacity, comparator)
Przykładowy kod:
Wynik:
W przeciwnym razie możesz także zdefiniować własny komparator:
źródło
Oto prosty przykład, którego możesz użyć do wstępnej nauki:
źródło