Comparator e Comparable

🧠 Objetivo do Tópico

Aprender:

  • Como ordenar objetos personalizados com Comparable e Comparator
  • Diferenças entre ambos
  • Boas práticas, formas corretas e incorretas
  • Sintaxe com classes anônimas, expressões lambda e métodos estáticos de comparação
  • Dicas de prova + 10 questões com respostas comentadas

🔍 1. Interface Comparable<T>

Você implementa essa interface na própria classe para definir ordem natural.

Exemplo: ordenando por nome (ordem alfabética)

public class Pessoa implements Comparable<Pessoa> {
  private String nome;
  private int idade;

  public Pessoa(String nome, int idade) {
    this.nome = nome;
    this.idade = idade;
  }

  @Override
  public int compareTo(Pessoa outra) {
    return this.nome.compareTo(outra.nome);
  }

  @Override
  public String toString() {
    return nome + " (" + idade + ")";
  }
}
List<Pessoa> lista = new ArrayList<>();
lista.add(new Pessoa("João", 30));
lista.add(new Pessoa("Ana", 25));
lista.add(new Pessoa("Carlos", 20));

Collections.sort(lista);
System.out.println(lista);

Saída: [Ana (25), Carlos (20), João (30)]
→ Ordem natural foi definida pelo compareTo().

🔀 2. Interface Comparator<T>

Você cria um comparador externo, útil quando:

  • Quer várias formas de ordenação
  • Não pode/quer modificar a classe original

Exemplo: ordenando por idade

Comparator<Pessoa> porIdade = new Comparator<>() {
  @Override
  public int compare(Pessoa p1, Pessoa p2) {
    return Integer.compare(p1.idade, p2.idade);
  }
};

Collections.sort(lista, porIdade);

Ou usando lambda:

lista.sort((p1, p2) -> Integer.compare(p1.idade, p2.idade));

Ou com método de comparação:

lista.sort(Comparator.comparing(p -> p.idade));

❌ Erros comuns (pegadinhas)

  • Usar compareTo retornando boolean — precisa retornar int
  • Esquecer de sobrescrever compareTo() se usa Comparable
  • Confundir Comparator com Comparable em provas
  • Esquecer que Comparator permite múltiplos critérios (ex: .thenComparing())
  • Usar == para comparar Strings ao invés de compareTo ou equals

✅ Boas práticas

  • Use Comparable para ordem natural (ex: nomes, números)
  • Use Comparator para outras ordenações (ex: por data, idade, tamanho)
  • Use Comparator.comparing() com lambdas para código limpo
  • Use thenComparing() para empates

📘 Exemplo com thenComparing

Comparator porIdadeENome = Comparator
.comparing(Pessoa::getIdade)
.thenComparing(Pessoa::getNome);

⌛Simulado

1. Qual método Comparable exige implementação?

Resposta: D

a) equals
b) hashCode
c) compare
d) compareTo

2. O que Collections.sort(lista) exige?

Resposta: C

a) Que o objeto use Comparator
b) Que a lista seja de Strings
c) Que os elementos implementem Comparable
d) Que a lista esteja ordenada

3. Qual o propósito de Comparator<T>?

Resposta: B

a) Substituir equals
b) Definir ordem de objetos sem modificar a classe original
c) Comparar objetos usando hashCode
d) Ser usado apenas com mapas

4. Dado:

Resposta: B

class Produto {
String nome;
double preco;
}

Qual opção ordena por preço usando lambda?

a) lista.sort((a, b) -> a.preco - b.preco);
b) lista.sort((a, b) -> Double.compare(a.preco, b.preco));
c) lista.sort((a, b) -> a.preco > b.preco);
d) Collections.sort(lista, Produto);

5. O que compareTo() deve retornar?

Resposta: B

a) true se objetos forem iguais
b) um número negativo, zero ou positivo
c) o menor número
d) uma String

6. É possível usar Comparator com TreeSet?

Resposta: B

a) Não
b) Sim, passando no construtor
c) Sim, desde que a classe seja abstract
d) Apenas se a classe implementar Comparable

7. Qual método combina dois comparadores?

Resposta: C

a) combine()
b) compareWith()
c) thenComparing()
d) alsoCompare()

8. Qual dessas expressões é inválida?

Resposta: B

a) Comparator.comparingInt(p -> p.idade);
b) Comparator.compare((a, b) -> a.idade);
c) Comparator.comparing(p -> p.nome);
d) Comparator.comparing(Pessoa::getIdade);

9. Quando dois objetos têm compareTo() == 0, eles são:

Resposta: B

a) Idênticos fisicamente
b) Considerados iguais na ordenação
c) Diferentes
d) Necessariamente null

10. O que acontece se dois objetos forem “iguais” em um TreeSet?

Resposta: B

a) Ambos são armazenados
b) Apenas um é armazenado
c) Gera exceção
d) Ordenação é ignorada

✅ Gabarito com Comentários

  1. dcompareTo é o método da interface Comparable.
  2. cComparable define a ordem natural.
  3. bComparator pode ordenar sem modificar a classe.
  4. bDouble.compare é a maneira correta.
  5. bcompareTo() retorna int, e deve indicar a ordem.
  6. bTreeSet aceita um Comparator no construtor.
  7. cthenComparing encadeia comparações.
  8. bComparator.compare() não existe, é compare(a, b) via instância.
  9. bcompareTo() == 0 indica “iguais na ordenação”, não equals().
  10. bTreeSet descarta duplicatas baseadas na ordenação.

🧾 Resumo

  • Comparable: implementado na própria classe, define a ordem natural.
  • Comparator: externo, pode ter múltiplas ordens e ser combinado.
  • Métodos importantes:
    • compareTo(T o)Comparable
    • compare(T o1, T o2)Comparator
    • Comparator.comparing, thenComparing, reversed()
  • Saber usar ambos é essencial para ordenações com Collections.sort, TreeSet, TreeMap, etc.

Deixe um comentário