Classificando uma coleção de objects

Se eu tiver uma lista simples de Strings:

List stringList = new ArrayList(); 

Eu posso classificá-lo com:

 Collections.sort(stringList); 

Mas suponha que eu tenha uma class Person:

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

E uma lista disso:

 List personList = new ArrayList(); 

E eu quero classificá-lo às vezes por nome, às vezes por idade, às vezes por país.

Qual é a maneira mais fácil de conseguir isso?

Eu sei que posso implementar a interface Comparable, mas isso parece me limitar a classificá-la por uma propriedade específica.

Implemente a interface do Comparador (uma vez para cada ordem de sorting diferente) e use o método Collections.sort () que usa um Comparator como parâmetro adicional.

Collections.sort pode ser chamado com um comparador personalizado. E esse comparador pode ser implementado para permitir a sorting em diferentes ordens de sorting. Aqui está um exemplo (para o seu modelo Person – com a idade como Integer):

 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 você usa assim (assumindo que as pessoas são um 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 } 

Obrigado aos respondentes. Para o benefício de outros, gostaria de include um exemplo completo.

A solução é criar as seguintes classs adicionais:

 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()); } } 

A lista pode então ser classificada assim:

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

A maneira do Java 8 de fazer isso é usar List.sort seguinte maneira:

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

Para citar Stuart Marks em sua resposta aqui .

Esta é a grande vantagem do método de extensão List.sort(cmp) sobre Collections.sort(list, cmp) . Pode parecer que esta é apenas uma pequena vantagem sintática sendo capaz de escrever myList.sort(cmp) vez de Collections.sort(myList, cmp) . A diferença é que myList.sort(cmp) , sendo um método de extensão de interface, pode ser substituído pela implementação de List específica. Por exemplo, ArrayList.sort(cmp) classifica a lista no local usando Arrays.sort() enquanto a implementação padrão implementa a técnica copy-sort-copyback antiga.

Você também pode usar o BeanComparator do apache commons beanutils, desta forma:

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

Implemente 3 tipos diferentes de Comparador.

você pode adicionar o comparador ao comando sort. O comparador que você definir classificará os elementos por nome, idade ou sempre.

 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(); } }); 

O método Collections.sort pode ser invocado com um segundo argumento que é o comparador a ser usado. Crie 3 comparadores e use o que você quer quando apropriado.

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

Eu fiz uma pergunta muito semelhante (sobre a pesquisa em vez de classificar), talvez haja alguma informação útil (acabei usando um enum que implementa o Comparator então eu passo o valor enum como um seletor de comparador).

Usando lambdaj ( http://code.google.com/p/lambdaj/ ) você pode conseguir o que você está perguntando da seguinte maneira:

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

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

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