La interfaz Comparable
Implemente Comparable para proporcionar un orden natural a una clase y usarlo con Collections.sort.
La interfaz Comparable es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.
La interfaz Comparable
Comparable<T> proporciona a una clase un orden natural. Impleméntela para poder ordenar las instancias con Collections.sort(), Arrays.sort() y colecciones ordenadas como TreeSet.
Implementar Comparable
Implemente compareTo(T other) para que devuelva un valor negativo (this < other), cero (iguales) o un valor positivo (this > 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)]El contrato de compareTo
Implementar Comparable correctamente exige cumplir un contrato:
- Antisimetría: sgn(a.compareTo(b)) == -sgn(b.compareTo(a))
- Transitividad: si a > b y b > c, entonces a > c
- Consistencia: se recomienda encarecidamente que a.compareTo(b) == 0 implique a.equals(b)
Comparar tipos primitivos de forma segura
No reste tipos primitivos en compareTo: un desbordamiento de enteros puede producir resultados incorrectos. Use Integer.compare(), Double.compare(), etc.
// 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
}Orden natural en TreeSet
Las clases que implementan Comparable se colocan automáticamente en colecciones ordenadas como TreeSet y 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 con varios campos
Para ordenar por varios campos, encadene las comparaciones: primero el campo principal y después el secundario si el principal es igual.
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
}
}Consistencia entre Comparable y equals
Se recomienda encarecidamente, aunque no es obligatorio, que a.compareTo(b) == 0 si y solo si a.equals(b). Incumplirlo provoca errores sutiles en conjuntos y 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 elementOrdenar con Collections.sort
Collections.sort() y Arrays.sort() usan el orden natural definido 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 en la búsqueda binaria
Collections.binarySearch() requiere que la lista esté ordenada según el orden natural y que sus elementos implementen 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 frente a Comparator
Diferencia principal:
- Comparable: define el orden natural de la propia clase; uno por clase
- Comparator: define un orden externo; admite un número ilimitado de órdenes combinables
Práctica: tabla de clasificación
Una tabla de clasificación que usa Comparable para establecer un orden natural descendente por puntuación.
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: 950Comprobación rápida
¿Qué devuelve compareTo() cuando el objeto actual es menor que el argumento?
Recapitulación: la interfaz Comparable
Aspectos clave:
- Implemente Comparable
para definir el orden natural de una clase - compareTo devuelve un valor negativo (menor), cero (igual) o un valor positivo (mayor)
- Use Integer.compare()/Double.compare(); nunca reste, debido al riesgo de desbordamiento
- Encadene comparaciones para ordenar por varios campos: principal → secundario
- Collections.sort, Arrays.sort, TreeSet y TreeMap usan el orden natural
- Comparable define UN orden; use Comparator para definir varios órdenes
Preguntas frecuentes
¿La lección «La interfaz Comparable» es gratis?
Sí — el texto completo de «La interfaz Comparable» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.
¿Qué aprenderé en «La interfaz Comparable»?
Implemente Comparable para proporcionar un orden natural a una clase y usarlo con Collections.sort. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Java Academy?
No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «La interfaz Comparable»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Java Academy?
Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- La interfaz Comparable
- Comparator y ordenación con lambdas
- Ordenación por varias claves con thenComparing
- Ordenación de arrays y colecciones en la práctica