Tenho uma classe chamada Person
com várias propriedades, por exemplo:
public class Person {
private int id;
private String name, address;
// Many more properties.
}
Muitos Person
objetos -são armazenados em um ArrayList<Person>
. Quero classificar esta lista por vários parâmetros de classificação e diferentes de vez em quando. Por exemplo, posso querer uma vez ordenar por ordem name
ascendente e depois address
decrescente, e outra vez apenas por ordem id
decrescente.
E não quero criar meus próprios métodos de classificação (ou seja, quero usar Collections.sort(personList, someComparator)
. Qual é a solução mais elegante que consegue isso?
comparator.reversed()
para decrescente ecomparator1.thenComparing(comparator2)
para encadear comparadores.Você pode criar comparadores para cada uma das propriedades que deseja classificar e, em seguida, tentar "encadeamento de comparadores" :-) assim:
fonte
Uma maneira é criar um
Comparator
que tenha como argumentos uma lista de propriedades pelas quais classificar, como mostra este exemplo.Ele pode então ser usado em código, por exemplo:
fonte
Uma abordagem seria compor
Comparator
s. Este poderia ser um método de biblioteca (tenho certeza que existe em algum lugar por aí).Usar:
Como alternativa, observe que
Collections.sort
é uma classificação estável. Se o desempenho não for absolutamente crucial, você deve ser a ordem secundária antes da primária.fonte
compose(nameComparator, compose(addressComparator, idComparator))
Isso seria um pouco melhor se Java tivesse métodos de extensão.Os comparadores permitem que você faça isso de forma fácil e natural. Você pode criar instâncias únicas de comparadores, seja na própria classe Person ou em uma classe Service associada à sua necessidade.
Exemplos, usando classes internas anônimas:
Se você tiver muitos, também poderá estruturar o código dos comparadores da maneira que desejar. Por exemplo, você poderia:
fonte
Acho que acoplar os classificadores à classe Person, como em sua resposta, não é uma boa ideia, porque acopla a comparação (geralmente voltada para os negócios) e o objeto do modelo próximos um do outro. Cada vez que você deseja alterar / adicionar algo ao classificador, você precisa tocar na classe de pessoa, o que geralmente é algo que você não deseja fazer.
Usar um serviço ou algo semelhante, que fornece instâncias do Comparator, como o proposto pelo KLE, parece muito mais flexível e extensível.
fonte
Minha abordagem é baseada na de Yishai. A principal lacuna é que não há como classificar primeiro ascendente para um atributo e depois descendente para outro. Isso não pode ser feito com enumerações. Para isso usei aulas. Porque SortOrder depende fortemente do tipo, prefiro implementá-lo como uma classe interna de pessoa.
A classe 'Person' com a classe interna 'SortOrder':
Um exemplo de uso da classe Person e seu SortOrder:
oRUMOo
fonte
Recentemente, escrevi um Comparador para classificar vários campos em um registro de String delimitado. Ele permite que você defina o delimitador, a estrutura do registro e as regras de classificação (algumas das quais são específicas do tipo). Você pode usar isso convertendo um registro de pessoa em uma string delimitada.
As informações necessárias são propagadas para o próprio Comparador, seja programaticamente ou por meio de um arquivo XML.
XML é validado por um arquivo XSD embutido no pacote. Por exemplo, abaixo está um layout de registro delimitado por tabulação com quatro campos (dois dos quais são classificáveis):
Você então usaria isso em java da seguinte forma:
A biblioteca pode ser encontrada aqui:
http://sourceforge.net/projects/multicolumnrowcomparator/
fonte
Suponha que
Coordinate
haja uma classe e seja necessário classificá-la das duas maneiras, de acordo com a coordenada X e a coordenada Y. Para isso, são necessários dois comparadores de diff. Abaixo está o exemplofonte