A Interface Comparable
Implemente Comparable para dar a uma classe uma ordenação natural e use-a com Collections.sort.
A Interface Comparable é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
A interface Comparable
Comparable<T> fornece uma ordem natural para uma classe. Implemente-a para tornar as instâncias ordenáveis com Collections.sort(), Arrays.sort() e coleções ordenadas, como TreeSet.
Implementando Comparable
Implemente compareTo(T other) retornando um valor negativo (este objeto < other), zero (iguais) ou um valor positivo (este objeto > other).
class Product implements Comparable<Product> {
private final String name;
private final double price;
Product(String name, double price) {
this.name = name; this.price = price;
}
@Override
public int compareTo(Product other) {
return Double.compare(this.price, other.price); // ascending by price
}
@Override public String toString() { return name + "($" + price + ")"; }
}
List<Product> products = new ArrayList<>(List.of(
new Product("Mouse", 29.99),
new Product("Laptop", 999.0),
new Product("Keyboard", 79.99)
));
Collections.sort(products);
System.out.println(products); // [Mouse($29.99), Keyboard($79.99), Laptop($999.0)]O contrato de compareTo
Implementar Comparable corretamente exige satisfazer um contrato:
- Antissimetria: sgn(a.compareTo(b)) == -sgn(b.compareTo(a))
- Transitividade: se a > b e b > c, então a > c
- Consistência: a.compareTo(b) == 0 implica a.equals(b); essa consistência é fortemente recomendada
Comparando tipos primitivos com segurança
Nunca subtraia tipos primitivos em compareTo: o estouro de inteiros pode produzir resultados incorretos. Use Integer.compare(), Double.compare() e outros métodos semelhantes.
// WRONG: integer subtraction can overflow
int compareTo(Player other) {
return this.score - other.score; // overflow if scores differ by > Integer.MAX_VALUE
}
// CORRECT: use Integer.compare
int compareTo(Player other) {
return Integer.compare(this.score, other.score);
}
// For strings: delegate to String.compareTo
int compareTo(Player other) {
return this.name.compareTo(other.name); // String handles it correctly
}Ordenação natural em TreeSet
As classes que implementam Comparable são inseridas automaticamente na posição correta em coleções ordenadas, como TreeSet e TreeMap.
class Priority implements Comparable<Priority> {
enum Level { LOW, MEDIUM, HIGH, CRITICAL }
final Level level;
final String task;
Priority(Level level, String task) { this.level = level; this.task = task; }
@Override
public int compareTo(Priority other) {
return this.level.compareTo(other.level); // enum ordinal order
}
@Override public String toString() { return level + ": " + task; }
}
TreeSet<Priority> queue = new TreeSet<>();
queue.add(new Priority(Priority.Level.CRITICAL, "Fix prod crash"));
queue.add(new Priority(Priority.Level.LOW, "Update docs"));
queue.add(new Priority(Priority.Level.HIGH, "Deploy feature"));
queue.forEach(System.out::println);
// LOW: Update docs
// HIGH: Deploy feature
// CRITICAL: Fix prod crashComparable com vários campos
Para ordenar por vários campos, encadeie as comparações: primeiro o campo principal e, se houver empate, o campo secundário.
class Employee implements Comparable<Employee> {
final String dept, name;
final double salary;
Employee(String dept, String name, double salary) {
this.dept = dept; this.name = name; this.salary = salary;
}
@Override
public int compareTo(Employee other) {
int deptCmp = this.dept.compareTo(other.dept);
if (deptCmp != 0) return deptCmp; // primary: by dept
return this.name.compareTo(other.name); // secondary: by name
}
}Consistência entre Comparable e equals
É fortemente recomendado, embora não seja obrigatório, que a.compareTo(b) == 0 se, e somente se, a.equals(b). Violar isso causa erros sutis em conjuntos e mapas ordenados.
// BigDecimal violates this: new BigDecimal("2.0").compareTo(new BigDecimal("2.00")) == 0
// but new BigDecimal("2.0").equals(new BigDecimal("2.00")) == false
// This causes TreeSet to treat them as equal (only one stored)
TreeSet<java.math.BigDecimal> set = new TreeSet<>();
set.add(new java.math.BigDecimal("2.0"));
set.add(new java.math.BigDecimal("2.00"));
System.out.println(set.size()); // 1 — compareTo-equal → same elementOrdenando com Collections.sort
Collections.sort() e Arrays.sort() usam a ordem natural definida por Comparable.
List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
Collections.sort(names); // natural alphabetical order
System.out.println(names); // [Alice, Bob, Charlie]
String[] arr = {"banana", "apple", "cherry"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); // [apple, banana, cherry]
// Stream sorted() uses natural order
names.stream().sorted().forEach(System.out::println);Comparable na busca binária
Collections.binarySearch() exige que a lista esteja ordenada pela ordem natural e que os elementos implementem Comparable.
List<Integer> sorted = new ArrayList<>(List.of(1, 3, 5, 7, 9, 11));
int idx = Collections.binarySearch(sorted, 7);
System.out.println("Found 7 at index: " + idx); // 3
int missing = Collections.binarySearch(sorted, 4);
System.out.println("4 not found, insertion point: " + (-missing - 1)); // 2Comparable versus Comparator
Distinção principal:
- Comparable: define a própria ordem natural da classe — uma por classe
- Comparator: define uma ordenação externa — ilimitada e combinável
Prática: classificação
Uma classificação que usa Comparable para definir naturalmente a ordem decrescente das pontuações.
class LeaderboardEntry implements Comparable<LeaderboardEntry> {
final String player;
final int score;
final long timestamp;
LeaderboardEntry(String player, int score) {
this.player = player; this.score = score;
this.timestamp = System.nanoTime();
}
@Override
public int compareTo(LeaderboardEntry other) {
int scoreCmp = Integer.compare(other.score, this.score); // descending
if (scoreCmp != 0) return scoreCmp;
return Long.compare(this.timestamp, other.timestamp); // earlier = higher
}
@Override public String toString() { return player + ": " + score; }
}
TreeSet<LeaderboardEntry> board = new TreeSet<>();
board.add(new LeaderboardEntry("Alice", 950));
board.add(new LeaderboardEntry("Bob", 1200));
board.add(new LeaderboardEntry("Carol", 950));
board.forEach(System.out::println);
// Bob: 1200 / Alice: 950 / Carol: 950Verificação rápida
O que compareTo() retorna quando o objeto atual é menor que o argumento?
Recapitulação: a interface Comparable
Principais aprendizados:
- Implemente Comparable<T> para definir a ordem natural de uma classe
- compareTo retorna um valor negativo (menor), zero (igual) ou positivo (maior)
- Use Integer.compare()/Double.compare(): nunca subtraia, devido ao risco de estouro
- Encadeie comparações para ordenar por vários campos: principal → secundário
- A ordem natural é usada por Collections.sort, Arrays.sort, TreeSet e TreeMap
- Comparable define UMA ordem; use Comparator para várias ordenações
Perguntas Frequentes
A aula “A Interface Comparable” é grátis?
Sim — o texto completo de “A Interface Comparable” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “A Interface Comparable”?
Implemente Comparable para dar a uma classe uma ordenação natural e use-a com Collections.sort. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “A Interface Comparable”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- A Interface Comparable
- Ordenação com Comparator e Lambdas
- Ordenação por Várias Chaves com thenComparing
- Ordenação de Matrizes e Coleções na Prática