Mam klasę o nazwie Person
z wieloma właściwościami, na przykład:
public class Person {
private int id;
private String name, address;
// Many more properties.
}
Wiele Person
-obiektów jest przechowywanych w pliku ArrayList<Person>
. Chcę posortować tę listę według wielu parametrów sortowania i różni się od czasu do czasu. Na przykład raz mógłbym chcieć posortować je name
rosnąco, a potem address
malejąco, a innym razem po prostu id
malejąco.
I nie chcę tworzyć własnych metod sortowania (tj. Chcę użyć Collections.sort(personList, someComparator)
. Jakie jest najbardziej eleganckie rozwiązanie, które to umożliwia?
comparator.reversed()
do zstępowania i możesz używaćcomparator1.thenComparing(comparator2)
do łączenia w łańcuchy komparatorów.Możesz utworzyć komparatory dla każdej właściwości, którą chcesz posortować, a następnie wypróbować „łańcuch porównawczy” :-) w następujący sposób:
źródło
Jednym ze sposobów jest utworzenie
Comparator
jako argumentów listy właściwości do sortowania, jak pokazano w tym przykładzie.Można go następnie użyć w kodzie, na przykład w ten sposób:
źródło
Jednym podejściem byłoby skomponowanie
Comparator
s. Może to być metoda biblioteczna (jestem pewien, że gdzieś tam istnieje).Posługiwać się:
Alternatywnie, zauważ, że
Collections.sort
jest to typ stabilny. Jeśli wydajność nie jest absolutnie kluczowa, sortowanie będzie drugorzędne przed podstawowym.źródło
compose(nameComparator, compose(addressComparator, idComparator))
Byłoby to trochę lepiej, gdyby Java miała metody rozszerzające.Komparatory pozwalają to zrobić bardzo łatwo i naturalnie. Możesz tworzyć pojedyncze wystąpienia komparatorów, w samej klasie Person lub w klasie Service powiązanej z twoimi potrzebami.
Przykłady, używając anonimowych klas wewnętrznych:
Jeśli masz wiele, możesz także dowolnie ustrukturyzować kod komparatorów . Na przykład możesz:
źródło
Myślę, że połączenie sortowników z klasą Person, tak jak w twojej odpowiedzi, nie jest dobrym pomysłem, ponieważ łączy porównanie (zwykle napędzane biznesowo) i obiekt modelu tak, aby były blisko siebie. Za każdym razem, gdy chcesz coś zmienić / dodać sortownik, musisz dotknąć klasy osoby, co zwykle jest czymś, czego nie chcesz robić.
Korzystanie z usługi lub czegoś podobnego, które zapewnia wystąpienia komparatora, takie jak proponowane przez KLE, brzmi znacznie bardziej elastycznie i rozszerzalnie.
źródło
Moje podejście jest oparte na podejściu Yishai. Główna luka polega na tym, że nie ma możliwości sortowania najpierw rosnąco dla atrybutu, a następnie malejąco dla innego. Nie można tego zrobić za pomocą wyliczeń. Do tego użyłem klas. Ponieważ SortOrder silnie zależy od typu, wolałem zaimplementować go jako wewnętrzną klasę osoby.
Klasa „Osoba” z klasą wewnętrzną „SortOrder”:
Przykład użycia klasy Person i jej SortOrder:
oRUMOo
źródło
Niedawno napisałem komparator, aby posortować wiele pól w rozdzielanym rekordzie typu String. Pozwala zdefiniować separator, strukturę rekordu i reguły sortowania (niektóre z nich są specyficzne dla typu). Możesz tego użyć, konwertując rekord Person na rozdzielany ciąg.
Wymagane informacje są wysyłane do samego komparatora, programowo lub za pośrednictwem pliku XML.
XML jest weryfikowany przez osadzony w pakiecie plik XSD. Na przykład poniżej przedstawiono układ rekordów rozdzielany tabulatorami z czterema polami (z których dwa można sortować):
Możesz użyć tego w javie w następujący sposób:
Bibliotekę można znaleźć tutaj:
http://sourceforge.net/projects/multicolumnrowcomparator/
źródło
Załóżmy, że istnieje klasa
Coordinate
i trzeba ją posortować w obie strony według współrzędnej X i Y. Potrzebne są do tego dwa różne komparatory. Poniżej znajduje się próbkaźródło