Oto samouczek dotyczący zamawiania obiektów:
Chociaż podam kilka przykładów, to i tak polecam je przeczytać.
Istnieją różne sposoby sortowania plików ArrayList
. Jeśli chcesz zdefiniować naturalne (domyślne) uporządkowanie , musisz pozwolić Contact
implementować Comparable
. Zakładając, że chcesz sortować domyślnie name
, zrób (dla uproszczenia pominięto kontrole null):
public class Contact implements Comparable<Contact> {
private String name;
private String phone;
private Address address;
public int compareTo(Contact other) {
return name.compareTo(other.name);
}
// Add/generate getters/setters and other boilerplate.
}
więc możesz po prostu to zrobić
List<Contact> contacts = new ArrayList<Contact>();
// Fill it.
Collections.sort(contacts);
Jeśli chcesz zdefiniować porządkowanie sterowane zewnętrznie (które zastępuje porządek naturalny), musisz utworzyć Comparator
:
List<Contact> contacts = new ArrayList<Contact>();
// Fill it.
// Now sort by address instead of name (default).
Collections.sort(contacts, new Comparator<Contact>() {
public int compare(Contact one, Contact other) {
return one.getAddress().compareTo(other.getAddress());
}
});
Możesz nawet zdefiniować Comparator
s w Contact
sobie, aby móc ich używać ponownie, zamiast tworzyć je za każdym razem:
public class Contact {
private String name;
private String phone;
private Address address;
// ...
public static Comparator<Contact> COMPARE_BY_PHONE = new Comparator<Contact>() {
public int compare(Contact one, Contact other) {
return one.phone.compareTo(other.phone);
}
};
public static Comparator<Contact> COMPARE_BY_ADDRESS = new Comparator<Contact>() {
public int compare(Contact one, Contact other) {
return one.address.compareTo(other.address);
}
};
}
które można wykorzystać w następujący sposób:
List<Contact> contacts = new ArrayList<Contact>();
// Fill it.
// Sort by address.
Collections.sort(contacts, Contact.COMPARE_BY_ADDRESS);
// Sort later by phone.
Collections.sort(contacts, Contact.COMPARE_BY_PHONE);
A żeby ubić górę, możesz rozważyć użycie ogólnego komparatora javabean :
public class BeanComparator implements Comparator<Object> {
private String getter;
public BeanComparator(String field) {
this.getter = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
}
public int compare(Object o1, Object o2) {
try {
if (o1 != null && o2 != null) {
o1 = o1.getClass().getMethod(getter, new Class[0]).invoke(o1, new Object[0]);
o2 = o2.getClass().getMethod(getter, new Class[0]).invoke(o2, new Object[0]);
}
} catch (Exception e) {
// If this exception occurs, then it is usually a fault of the developer.
throw new RuntimeException("Cannot compare " + o1 + " with " + o2 + " on " + getter, e);
}
return (o1 == null) ? -1 : ((o2 == null) ? 1 : ((Comparable<Object>) o1).compareTo(o2));
}
}
którego możesz użyć w następujący sposób:
// Sort on "phone" field of the Contact bean.
Collections.sort(contacts, new BeanComparator("phone"));
(jak widać w kodzie, prawdopodobnie pola puste są już zakryte, aby uniknąć NPE podczas sortowania)
String.CASE_INSENSITIVE_ORDER
i przyjaciół, ale podoba mi się. Sprawia, że wynikowy kod jest łatwiejszy do odczytania.static
a może ifinal
też ... Lub coś w tym rodzaju ...(o1 == null && o2 == null) ? 0 :
na początku tej linii powrotu?)Oprócz tego, co już zostało opublikowane, powinieneś wiedzieć, że od Java 8 możemy skrócić nasz kod i napisać go tak:
lub ponieważ Lista ma teraz
sort
metodęWyjaśnienie:
Od wersji Java 8 interfejsy funkcjonalne (interfejsy z tylko jedną metodą abstrakcyjną - mogą mieć więcej metod domyślnych lub statycznych) można łatwo zaimplementować za pomocą:
arguments -> body
source::method
.Ponieważ
Comparator<T>
ma tylko jedną abstrakcyjną metodę,int compare(T o1, T o2)
jest to interfejs funkcjonalny.Więc zamiast (przykład z odpowiedzi @BalusC )
możemy zredukować ten kod do:
Możemy uprościć tę (lub dowolną) lambdę, pomijając
{return
...}
Więc zamiast
możemy pisać
Teraz
Comparator
mamy również metody statyczne, takie jakcomparing(FunctionToComparableValue)
lub,comparing(FunctionToValue, ValueComparator)
których moglibyśmy użyć do łatwego tworzenia komparatorów, które powinny porównywać określone wartości z obiektów.Innymi słowy, możemy przepisać powyższy kod jako
źródło
Ta strona zawiera wszystko, co musisz wiedzieć o sortowaniu kolekcji, takich jak ArrayList.
Zasadniczo musisz
Contact
spraw, aby Twoja klasa implementowałaComparable
interfejs przezpublic int compareTo(Contact anotherContact)
w niej metody .Collections.sort(myContactList);
,myContactList
jestArrayList<Contact>
(lub jakikolwiek inny zbiórContact
).Istnieje również inny sposób, polegający na utworzeniu klasy komparatora, o czym możesz przeczytać również na połączonej stronie.
Przykład:
źródło
BalusC i bguiz udzieliły już bardzo wyczerpujących odpowiedzi na temat korzystania z wbudowanych komparatorów Javy.
Chcę tylko dodać, że kolekcje Google mają klasę Ordering, która jest bardziej „potężna” niż standardowe komparatory. Może warto to sprawdzić. Możesz robić fajne rzeczy, takie jak składanie kolejności, odwracanie ich, porządkowanie w zależności od wyniku funkcji dla twoich obiektów ...
Oto post na blogu, w którym wymieniono niektóre z jego zalet.
źródło
Musisz sprawić, aby klasy Contact implementowały porównywalną , a następnie zaimplementuj
compareTo(Contact)
metodę. W ten sposób Kolekcje.sort będą mogły je dla Ciebie sortować. Na stronie, z którą się łączyłem, funkcja compareTo „zwraca ujemną liczbę całkowitą, zero lub dodatnią liczbę całkowitą, ponieważ ten obiekt jest mniejszy, równy lub większy od określonego obiektu”.Na przykład, jeśli chcesz posortować według nazwy (od A do Z), Twoja klasa wyglądałaby tak:
źródło
Używając lambdaj , możesz posortować kolekcję swoich kontaktów (na przykład według ich nazw) w następujący sposób
lub przez ich adres:
i tak dalej. Mówiąc bardziej ogólnie, oferuje DSL do uzyskiwania dostępu do kolekcji i manipulowania nimi na wiele sposobów, takich jak filtrowanie lub grupowanie kontaktów na podstawie pewnych warunków, agregowanie niektórych wartości ich właściwości itp.
źródło
Kolekcje.sort to dobra implementacja. Jeśli nie masz implementacji porównywalnej dla Contact, musisz przejść implementację komparatora
Nutowy:
Sortowanie przez scalanie jest prawdopodobnie lepsze niż większość algorytmów wyszukiwania, które możesz wykonać.
źródło
Zrobiłem to w następujący sposób. number i name to dwa arraylist. Muszę posortować nazwę. Jeśli zdarzy się jakakolwiek zmiana w kolejności nazewnictwa, wówczas arraylista numerów również zmieni swoją kolejność.
źródło
użyj tej metody:
`
i użyj:
mySortedlist = sortList(myList);
Nie ma potrzeby wdrażania komparatora w swojej klasie. Jeśli chcesz zmienić kolejność odwrotną1
i-1
źródło
Ok, wiem, że odpowiedziano na to dawno temu ... ale oto kilka nowych informacji:
Powiedzmy, że dana klasa Contact ma już zdefiniowaną naturalną kolejność poprzez implementację Comparable, ale chcesz zastąpić tę kolejność, powiedzmy, po nazwie. Oto nowoczesny sposób, aby to zrobić:
W ten sposób najpierw posortuje według nazwy (w odwrotnej kolejności), a następnie w przypadku kolizji nazw powróci do „naturalnego” porządku zaimplementowanego przez samą klasę Contact.
źródło
Powinieneś użyć funkcji Arrays.sort. Klasy zawierające powinny implementować Comparable.
źródło