0Pricing
Java Academy · Leçon

L’interface Comparable

Implémentez Comparable pour donner un ordre naturel à une classe et utilisez-le avec Collections.sort.

L’interface Comparable est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.

L'interface Comparable

Comparable<T> confère à une classe un ordre naturel. Implémentez-la pour rendre ses instances triables avec Collections.sort(), Arrays.sort() et des collections triées comme TreeSet.

Implémenter Comparable

Implémentez compareTo(T other) en renvoyant une valeur négative (this < other), zéro (égalité) ou une valeur positive (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)]

Le contrat de compareTo

Implémenter Comparable correctement nécessite de respecter un contrat :

  • Antisymétrie : sgn(a.compareTo(b)) == -sgn(b.compareTo(a))
  • Transitivité : si a > b et b > c, alors a > c
  • Cohérence : a.compareTo(b) == 0 implique a.equals(b) ; cette relation est vivement recommandée

Comparer les types primitifs en toute sécurité

Ne soustrayez jamais des types primitifs dans compareTo : un dépassement de capacité d'un entier peut produire un résultat incorrect. Utilisez 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
}

Ordre naturel dans TreeSet

Les classes qui implémentent Comparable sont automatiquement positionnées dans les collections triées comme TreeSet et 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 crash

Comparable à plusieurs champs

Pour trier selon plusieurs champs, enchaînez les comparaisons : d'abord le champ principal, puis le champ secondaire si le premier est égal.

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

Cohérence entre Comparable et equals

Il est vivement recommandé, sans être obligatoire, que a.compareTo(b) == 0 si et seulement si a.equals(b). Le non-respect de cette règle provoque des erreurs subtiles dans les ensembles et les maps triés.

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

Trier avec Collections.sort

Collections.sort() et Arrays.sort() utilisent l'ordre naturel défini par 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 dans une recherche binaire

Collections.binarySearch() exige que la liste soit triée selon l'ordre naturel et que ses éléments implémentent 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)); // 2

Comparable et Comparator

Distinction principale :

  • Comparable : définit l'ordre naturel propre à la classe — un seul par classe
  • Comparator : définit un ordre externe — en nombre illimité et composable

En pratique : classement

Un classement utilisant Comparable pour obtenir un ordre naturel décroissant selon le 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: 950

Vérification rapide

Que renvoie compareTo() lorsque l'objet courant est inférieur à l'argument ?

Récapitulatif : l'interface Comparable

Points essentiels :

  • Implémentez Comparable<T> pour définir l'ordre naturel d'une classe
  • compareTo renvoie une valeur négative (inférieure), zéro (égale) ou positive (supérieure)
  • Utilisez Integer.compare()/Double.compare() — ne soustrayez jamais de valeurs (risque de dépassement de capacité)
  • Enchaînez les comparaisons pour un tri sur plusieurs champs : principal → secondaire
  • L'ordre naturel est utilisé par Collections.sort, Arrays.sort, TreeSet et TreeMap
  • Comparable définit UN ordre ; utilisez Comparator pour plusieurs ordres

Questions Fréquemment Posées

La leçon « L’interface Comparable » est-elle gratuite ?

Oui — le texte complet de « L’interface Comparable » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « L’interface Comparable » ?

Implémentez Comparable pour donner un ordre naturel à une classe et utilisez-le avec Collections.sort. Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Java Academy ?

Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « L’interface Comparable » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?

Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. L’interface Comparable
  2. Tri avec Comparator et des lambdas
  3. Tri multicritère avec thenComparing
  4. Trier des tableaux et des collections en pratique
← Retour à Java Academy