Ordinamento di una raccolta di oggetti

Se ho una semplice lista di stringhe:

List stringList = new ArrayList(); 

Posso ordinarlo con:

 Collections.sort(stringList); 

Ma supponiamo di avere una class Person:

 public class Person { private String name; private Integer age; private String country; } 

E un elenco di esso:

 List personList = new ArrayList(); 

E voglio ordinarlo a volte per nome, a volte per età, a volte per paese.

Qual è il modo più semplice per farlo?

So che posso implementare l’interfaccia Comparable, ma sembra che mi limiti a selezionarlo per una proprietà specifica.

Implementare l’interfaccia di Comparator (una volta per ogni diverso ordinamento) e utilizzare il metodo Collections.sort () che accetta un Comparatore come parametro aggiuntivo.

Collections.sort può essere chiamato con un comparatore personalizzato. E questo comparatore può essere implementato per consentire l’ordinamento in diversi ordinamenti. Ecco un esempio (per il tuo modello di persona – con età come numero intero):

 public class FlexiblePersonComparator implements Comparator { public enum Order {Name, Age, Country} private Order sortingBy = Name; @Override public int compare(Person person1, Person person2) { switch(sortingBy) { case Name: return person1.name.compareTo(person2.name); case Age: return person1.age.compareTo(person2.age); case Country: return person1.country.compareTo(person2.country); } throw new RuntimeException("Practically unreachable code, can't be thrown"); } public void setSortingBy(Order sortBy) { this.sortingBy = sortingBy; } } 

E tu lo usi così (assumendo che le persone siano un campo):

 public void sortPersonsBy(FlexiblePersonComparator.Order sortingBy) { List persons = this.persons; // useless line, just for clarification FlexiblePersonComparator comparator = new FlexiblePersonComparator(); comparator.setSortingBy(sortingBy); Collections.sort(persons, comparator); // now we have a sorted list } 

Grazie ai soccorritori. Per il bene degli altri, vorrei includere un esempio completo.

La soluzione è creare le seguenti classi aggiuntive:

 public class NameComparator implements Comparator { public int compare(Person o1, Person o2) { return o1.getName().compareTo(o2.getName()); } } public class AgeComparator implements Comparator { public int compare(Person o1, Person o2) { return o1.getAge().compareTo(o2.getAge()); } } public class CountryComparator implements Comparator { public int compare(Person o1, Person o2) { return o1.getCountry().compareTo(o2.getCountry()); } } 

L’elenco può quindi essere ordinato in questo modo:

 Collections.sort(personList, new NameComparator()); Collections.sort(personList, new AgeComparator()); Collections.sort(personList, new CountryComparator()); 

Il modo Java 8 per farlo è usare List.sort come segue:

 personList.sort(Comparator.comparing(Person::getName)); 

Per citare Stuart Marks nella sua risposta qui .

Questo è il grande vantaggio del metodo di estensione List.sort(cmp) su Collections.sort(list, cmp) . Potrebbe sembrare che questo sia solo un piccolo vantaggio sintattico in grado di scrivere myList.sort(cmp) invece di Collections.sort(myList, cmp) . La differenza è che myList.sort(cmp) , essendo un metodo di estensione dell’interfaccia, può essere sovrascritto dall’implementazione specifica List . Ad esempio, ArrayList.sort(cmp) ordina in locale l’elenco utilizzando Arrays.sort() mentre l’implementazione predefinita implementa la vecchia tecnica copyout-sort-copyback.

Puoi anche usare BeanComparator da beanutils di apache commons, in questo modo:

 Collections.sort(personList, new BeanComparator("name")); 

Implementa 3 diversi tipi di Comparatore.

è ansible aggiungere il comparatore al comando di ordinamento. Il comparatore che definisci, ordinerà gli elementi per nome, età o cosa mai.

 Collections.sort(list, new Comparator() { public int compare(Object arg0, Object arg1) { if (!(arg0 instanceof Person)) { return -1; } if (!(arg1 instanceof Person)) { return -1; } Person pers0 = (Person)arg0; Person pers1 = (Person)arg1; // COMPARE NOW WHAT YOU WANT // Thanks to Steve Kuo for your comment! return pers0.getAge() - pers1.getAge(); } }); 

Il metodo Collections.sort può essere invocato con un secondo argomento che è il comparatore da utilizzare. Crea 3 comparatori e usa quello che vuoi quando appropriato.

 Collections.sort(list , new Comparator() { public int compare(Object o1, Object o2) { ... } }); 

Ho fatto una domanda molto simile (sulla ricerca piuttosto che sull’ordinamento), forse ci sono alcune informazioni utili (ho finito per usare un enum che implementa Comparator così ho passato il valore enum come selettore di confronto).

Usando lambdaj ( http://code.google.com/p/lambdaj/ ) puoi ottenere ciò che stai chiedendo nel seguente modo:

sort (personList, on (Person.class) .getName ());

sort (personList, on (Person.class) .getAge ());

sort (personList, on (Person.class) .getCountry ());