L'interfaccia Comparable
Implementi Comparable per assegnare a una classe un ordinamento naturale e lo utilizzi con Collections.sort.
L'interfaccia Comparable è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.
L'interfaccia Comparable
Comparable<T> assegna a una classe un ordinamento naturale. La implementi per rendere le istanze ordinabili con Collections.sort(), Arrays.sort() e con collezioni ordinate come TreeSet.
Implementare Comparable
Implementi compareTo(T other) restituendo un valore negativo (this < other), zero (uguale) o 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)]Il contratto di compareTo
Implementare Comparable correttamente richiede il rispetto di un contratto:
- Antisimmetria: sgn(a.compareTo(b)) == -sgn(b.compareTo(a))
- Transitività: se a > b e b > c, allora a > c
- Coerenza: a.compareTo(b) == 0 implica a.equals(b); questa corrispondenza è fortemente consigliata
Confrontare i primitivi in sicurezza
Non sottragga mai valori primitivi in compareTo: un overflow degli interi può produrre risultati errati. Utilizzi Integer.compare(), Double.compare() e così via.
// 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
}Ordinamento naturale in TreeSet
Le classi che implementano Comparable vengono inserite automaticamente nella posizione corretta di collezioni ordinate come 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 su più campi
Per ordinare in base a più campi, concateni i confronti: prima quello principale, poi quello secondario se il primo restituisce un valore uguale.
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
}
}Coerenza tra Comparable ed equals
È fortemente consigliato, ma non obbligatorio, che a.compareTo(b) == 0 se e solo se a.equals(b). La violazione di questa regola causa errori difficili da individuare nei set e nelle mappe ordinate.
// 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 elementOrdinare con Collections.sort
Collections.sort() e Arrays.sort() utilizzano l'ordinamento naturale definito da 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 nella ricerca binaria
Collections.binarySearch() richiede che la lista sia ordinata secondo l'ordinamento naturale e che gli elementi implementino 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 e Comparator a confronto
Differenza principale:
- Comparable: definisce l'ordinamento naturale della classe, uno solo per classe
- Comparator: definisce un ordinamento esterno, senza limiti e componibile
Applicazione pratica: classifica
Una classifica che utilizza Comparable per ottenere un ordinamento naturale decrescente in base al punteggio.
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 rapida
Che cosa restituisce compareTo() quando l'oggetto corrente è minore dell'argomento?
Riepilogo: l'interfaccia Comparable
Punti chiave:
- Implementi Comparable<T> per definire l'ordinamento naturale di una classe
- compareTo restituisce un valore negativo (minore), zero (uguale) o positivo (maggiore)
- Utilizzi Integer.compare()/Double.compare(): non sottragga mai, a causa del rischio di overflow
- Concateni i confronti per ordinare più campi: principale → secondario
- L'ordinamento naturale viene utilizzato da Collections.sort, Arrays.sort, TreeSet e TreeMap
- Comparable definisce UN solo ordinamento; utilizzi Comparator per ordini diversi
Domande Frequenti
La lezione «L'interfaccia Comparable» è gratuita?
Sì — il testo completo di «L'interfaccia Comparable» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.
Cosa imparerò in «L'interfaccia Comparable»?
Implementi Comparable per assegnare a una classe un ordinamento naturale e lo utilizzi con Collections.sort. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Java Academy?
Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «L'interfaccia Comparable»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Java Academy?
Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- L'interfaccia Comparable
- Comparator e ordinamento con lambda
- Ordinamento per più chiavi con thenComparing
- Ordinare array e collezioni nella pratica