Interfacet Comparable
Implementér Comparable for at give en klasse en naturlig sorteringsrækkefølge, og brug den med Collections.sort.
Interfacet Comparable er en gratis Java Academy-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Java Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Java Academy-kurset indeholder 4 lektioner i alt.
Grænsefladen Comparable
Comparable<T> giver en klasse en naturlig sorteringsrækkefølge. Implementér den for at gøre instanser sorterbare med Collections.sort(), Arrays.sort() og sorterede samlinger som TreeSet.
Implementering af Comparable
Implementér compareTo(T other), så den returnerer en negativ værdi (this < other), nul (ens) eller en positiv værdi (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)]Kontrakten for compareTo
En korrekt implementering af Comparable skal opfylde en kontrakt:
- Antisymmetri: sgn(a.compareTo(b)) == -sgn(b.compareTo(a))
- Transitivitet: Hvis a > b og b > c, så er a > c
- Konsistens: a.compareTo(b) == 0 medfører a.equals(b), hvilket anbefales kraftigt
Sikker sammenligning af primitive værdier
Træk aldrig primitive værdier fra hinanden i compareTo — heltalsoverløb kan give forkerte resultater. Brug Integer.compare(), Double.compare() osv.
// 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
}Naturlig sorteringsrækkefølge i TreeSet
Klasser, der implementerer Comparable, placeres automatisk korrekt i sorterede samlinger som TreeSet og 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 med flere felter
Hvis du vil sortere efter flere felter, skal du kæde sammenligningerne: først det primære felt og derefter det sekundære, hvis det primære er ens.
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
}
}Konsistens mellem Comparable og equals
Det anbefales kraftigt, men er ikke et krav, at a.compareTo(b) == 0 netop når a.equals(b). Hvis dette overtrædes, kan det give subtile fejl i sorterede sæt og maps.
// 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 elementSortering med Collections.sort
Collections.sort() og Arrays.sort() bruger den naturlige rækkefølge, der er defineret af 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 i binær søgning
Collections.binarySearch() kræver, at listen er sorteret efter den naturlige rækkefølge, og at elementerne implementerer 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 kontra Comparator
Den vigtigste forskel:
- Comparable: definerer klassens egen naturlige sorteringsrækkefølge — én pr. klasse
- Comparator: definerer en ekstern sorteringsrækkefølge — et ubegrænset antal, som kan sammensættes
Praktisk: Rangliste
En rangliste, der bruger Comparable til en naturlig rækkefølge med faldende score.
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: 950Hurtigt tjek
Hvad returnerer compareTo(), når det aktuelle objekt er mindre end argumentet?
Opsamling: Grænsefladen Comparable
Vigtigste pointer:
- Implementér Comparable<T> for at definere en klasses naturlige sorteringsrækkefølge
- compareTo returnerer negativ (mindre), nul (ens) eller positiv (større)
- Brug Integer.compare()/Double.compare() — træk aldrig værdier fra hinanden (risiko for overløb)
- Kæd sammenligninger ved sortering efter flere felter: primært → sekundært
- Den naturlige rækkefølge bruges af Collections.sort, Arrays.sort, TreeSet og TreeMap
- Comparable definerer ÉN rækkefølge; brug Comparator til flere rækkefølger
Lær Java med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 104
- Lektioner
- 374
Ofte stillede spørgsmål
Er lektionen “Interfacet Comparable” gratis?
Ja — hele teksten til “Interfacet Comparable” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Java Academy-kurset, skal du opgradere til CoddyKit PRO. Java Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Interfacet Comparable”?
Implementér Comparable for at give en klasse en naturlig sorteringsrækkefølge, og brug den med Collections.sort. Du øver dig i Java Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Java Academy?
Der kræves ingen tidligere erfaring. Java Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.
Hvor lang tid tager lektionen “Interfacet Comparable”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Java Academy-lektion?
Ja. Alle Java Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Interfacet Comparable
- Comparator og sortering med lambdaer
- Sortering efter flere nøgler med thenComparing
- Sortering af arrays og samlinger i praksis