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)
sobreCollections.sort(list, cmp)
. Pode parecer que esta é apenas uma pequena vantagem sintática sendo capaz de escrevermyList.sort(cmp)
vez deCollections.sort(myList, cmp)
. A diferença é quemyList.sort(cmp)
, sendo um método de extensão de interface, pode ser substituído pela implementação deList
específica. Por exemplo,ArrayList.sort(cmp)
classifica a lista no local usandoArrays.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 ());