Uma coleção de resumos, para ajudar os que precisam daquele empurrão.
Um comparator serve para definir um critério pelo qual se podem comparar duas classes. Este tipo de comparações são normalmente usadas ordenar elementos de uma lista ou inserir corretamente numa árvore de procura.
Durante este resumo vai ser varias vezes referenciada a seguinte classe:
public class Aluno{
private String nome;
private int nota;
/* construtores e getter/setters */
}
Para criar um comparator temos apenas de definir uma classe que implemente Comparator.
Se quisermos ordenar por ordem de notas, criamos o seguinte comparator.
public class AlunoComparator implements Comparator<Aluno>{
public int compare(Aluno a1, Aluno a2){
return Integer.compare(a1.getNota(), a2.getNota());
}
}
Os tipos básicos (int
, float
, double
, …) já tem definidos na
respetiva classe métodos para os comparar.
Para o utilizar apenas temos de o passar a algum método ou construtor que necessite de um.
List<Aluno> alunosPorNota = new ArrayList<>();
// inserir montes de alunos
alunosPorNota.sort(new AlunoComparator());
Neste caso o método sort ira ordenar por ordem crescente de notas os alunos da lista.
Se quisermos ordenar pela ordem inversa podemos utilizar o método
reversed disponibilizado por defeito em todos os Comparator
s
alunosPorNota.sort(new AlunosComparator().reversed());
Para criar um SortedSet, neste caso, temos de passar um comparator ao criar uma instância.
SortedSet<Aluno> alunos = new TreeSet<>(new AlunoComparator());
Assim sempre que for adicionado um novo aluno a este TreeSet este irá ser inserido de forma ordenada.
Em vez de criarmos uma classe nova para comparar objetos de uma outra
classe podemos também criar comparators com lambdas
e outros
métodos pré-definidos.
Utilizando a classe da secção anterior, os alunos podem ser ordenados das seguintes formas.
alunosPorNota.sort(Comparator.comparingInt(Aluno::getNota));
alunosPorNome.sort(Comparator.comparing(Aluno::getNome)); //O resultado do método tem de ser
//comparable (ver secção seguinte)
alunosPorNota.sort((a1, a2) -> Integer.compare(a1.getNota(), a2.getNota()));
O primeiro pode também ser invertido. [1]
alunosPorNota.sort(Comparator.comparingInt(Aluno::getNota).reversed());
Outro método de comparar objetos de uma classe é fazer essa classe comparável.
Podemos definir que, por defeito, os Alunos podem ser comparados por nome implementando a interface Comparable, que obriga à implementação do método compareTo.
public class Aluno implements Comparable<Aluno> {
private String nome;
public int compareTo(Aluno aluno){
return this.nome.compareTo(aluno.getNome());
}
}
Nota: As strings são Comparable
.
Podemos agora ter uma lista ordenada por nome da seguinte forma:
alunosPorNome.sort(Comparator.naturalOrder());
Agora que Aluno
é Comparable podemos criar uma estrutura ordenada
sem nos preocuparmos com o comparator::
SortedSet<Aluno> alunos = new TreeSet<>();
alunosPorNome.sort((new Comparator<Aluno>() {
@Override
public int compare(Aluno a1, Aluno a2){
return a1.getNome().compareTo(a2.getNome());
}
}).reversed());
A isto chama-se uma classe anónima, que faz uso da interface
funcional Comparator
.