0Pricing
Java Academy · Lektion

Die Comparable-Schnittstelle

Implementieren Sie Comparable, um einer Klasse eine natürliche Ordnung zu geben, und verwenden Sie sie mit Collections.sort.

Die Comparable-Schnittstelle ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Das Comparable-Interface

Comparable<T> verleiht einer Klasse eine natürliche Ordnung. Implementieren Sie es, damit Instanzen mit Collections.sort(), Arrays.sort() und sortierten Collections wie TreeSet sortiert werden können.

Comparable implementieren

Implementieren Sie compareTo(T other). Die Methode muss einen negativen Wert (this < other), null (gleich) oder einen positiven Wert (this > other) zurückgeben.

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)]

Der compareTo-Vertrag

Eine korrekte Implementierung von Comparable muss einen Vertrag erfüllen:

  • Antisymmetrie: sgn(a.compareTo(b)) == -sgn(b.compareTo(a))
  • Transitivität: Wenn a > b und b > c gilt, dann gilt auch a > c
  • Konsistenz: Aus a.compareTo(b) == 0 folgt, dass a.equals(b) gilt; dies wird dringend empfohlen

Primitive Werte sicher vergleichen

Subtrahieren Sie niemals primitive Werte in compareTo – ein Integer-Overflow kann zu falschen Ergebnissen führen. Verwenden Sie stattdessen Integer.compare(), Double.compare() usw.

// 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
}

Natürliche Ordnung in TreeSet

Klassen, die Comparable implementieren, werden automatisch in sortierten Collections wie TreeSet und TreeMap eingeordnet.

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 crash

Comparable mit mehreren Feldern

Um nach mehreren Feldern zu sortieren, verketten Sie Vergleiche: zuerst das primäre Feld, dann bei Gleichheit das sekundäre.

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
    }
}

Konsistenz von Comparable und equals

Es wird dringend empfohlen, aber nicht vorausgesetzt, dass a.compareTo(b) == 0 genau dann gilt, wenn a.equals(b) gilt. Ein Verstoß führt zu schwer erkennbaren Fehlern in sortierten Mengen und 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 element

Mit Collections.sort sortieren

Collections.sort() und Arrays.sort() verwenden die von Comparable definierte natürliche Ordnung.

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 bei der binären Suche

Collections.binarySearch() setzt voraus, dass die Liste nach der natürlichen Ordnung sortiert ist und die Elemente Comparable implementieren.

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)); // 2

Comparable und Comparator im Vergleich

Der entscheidende Unterschied:

  • Comparable: definiert die eigene natürliche Ordnung einer Klasse – eine pro Klasse
  • Comparator: definiert eine externe Ordnung – beliebig viele, miteinander kombinierbare

Praxis: Rangliste

Eine Rangliste, die Comparable für eine natürliche, nach Punktzahl absteigende Ordnung verwendet.

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: 950

Schnelltest

Was gibt compareTo() zurück, wenn das aktuelle Objekt kleiner als das Argument ist?

Zusammenfassung: Das Comparable-Interface

Die wichtigsten Erkenntnisse:

  • Implementieren Sie Comparable<T>, um die natürliche Ordnung einer Klasse zu definieren
  • compareTo gibt einen negativen Wert (kleiner), null (gleich) oder einen positiven Wert (größer) zurück
  • Verwenden Sie Integer.compare()/Double.compare() – subtrahieren Sie niemals (Overflow-Risiko)
  • Verketten Sie Vergleiche für die Sortierung nach mehreren Feldern: primär → sekundär
  • Die natürliche Ordnung wird von Collections.sort, Arrays.sort, TreeSet und TreeMap verwendet
  • Comparable definiert EINE Ordnung; verwenden Sie Comparator für mehrere Ordnungen

Häufig gestellte Fragen

Ist die Lektion „Die Comparable-Schnittstelle“ kostenlos?

Ja — der vollständige Text von „Die Comparable-Schnittstelle“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Die Comparable-Schnittstelle“?

Implementieren Sie Comparable, um einer Klasse eine natürliche Ordnung zu geben, und verwenden Sie sie mit Collections.sort. Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Java Academy zu starten?

Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Die Comparable-Schnittstelle“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?

Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Die Comparable-Schnittstelle
  2. Comparator und Sortieren mit Lambdas
  3. Sortieren nach mehreren Schlüsseln mit thenComparing
  4. Arrays und Collections in der Praxis sortieren
← Zurück zu Java Academy