Seb-Info

Java (partie 4)

Java (partie 4)

Comparer et trier des objets (equals/hashCode, Comparable, Comparator)

Objectif

Implémenter correctement l’égalité logique, l’ordre naturel et des ordres multiples pour trier et utiliser TreeSet/TreeMap.

Exemple complet


package model;
import java.util.Objects;

public class Student2 implements Comparable<Student2> {
    private final String id;
    private final String name;
    private final double average;

    public Student2(String id, String name, double average) {
        this.id = id; this.name = name; this.average = average;
    }
    public String id(){ return id; }
    public String name(){ return name; }
    public double average(){ return average; }

    @Override public boolean equals(Object o){
        if (this == o) return true;
        if (!(o instanceof Student2 s)) return false;
        return Objects.equals(id, s.id);
    }
    @Override public int hashCode(){ return Objects.hash(id); }

    // Ordre naturel : moyenne décroissante puis nom croissant puis id
    @Override public int compareTo(Student2 o){
        int c = -Double.compare(this.average, o.average);
        if (c != 0) return c;
        c = this.name.compareTo(o.name);
        if (c != 0) return c;
        return this.id.compareTo(o.id);
    }
    @Override public String toString(){
        return "%s(%.2f)".formatted(name, average);
    }
}
  

// src/app/CompareDemo.java
package app;
import model.Student2;
import java.util.*;

public class CompareDemo {
    public static void main(String[] args) {
        List<Student2> l = List.of(
            new Student2("S1","Alice",14.5),
            new Student2("S2","Bob",14.5),
            new Student2("S3","Chloé",16.0),
            new Student2("S4","David",9.5)
        );

        // Tri selon l'ordre naturel (Comparable)
        var a = new ArrayList<>(l);
        Collections.sort(a);
        System.out.println(a);

        // Ordre alternatif: par nom puis moyenne croissante
        var b = new ArrayList<>(l);
        b.sort(Comparator.comparing(Student2::name)
                         .thenComparingDouble(Student2::average));
        System.out.println(b);

        // TreeSet impose un ordre de tri cohérent
        var set = new java.util.TreeSet<Student2>(l);
        System.out.println(set);
    }
}
  

TP (à rendre)

  1. Créer une classe Product{sku, label, price, rating} (égalité sur sku).
  2. Implémenter Comparable pour un ordre naturel : rating décroissant, puis prix croissant, puis label.
  3. Écrire 2 Comparator :
    • a) par prix croissant puis rating décroissant,
    • b) par label, insensible à la casse.
  4. Tester dans un TreeSet et expliquer pourquoi certains éléments peuvent être “considérés égaux” selon l’ordre.
Corrigé (pistes)

Comparator<Product> byPrice = Comparator.comparingDouble(Product::price)
    .thenComparing(Comparator.comparing(Product::rating).reversed())
    .thenComparing(p -> p.label().toLowerCase());
    

Vigilances

  • Ordre de tri (compareTo/Comparator) doit être cohérent avec equals si on utilise TreeSet/TreeMap.
  • Ne jamais retourner des résultats incohérents (antisymétrie, transitivité).

Ce contenu est réservé aux membres du site. Si vous êtes un utilisateur existant, veuillez vous connecter. Les nouveaux utilisateurs peuvent s'inscrire ci-dessous.

Connexion pour les utilisateurs enregistrés
   
Nouvel utilisateur ?
*Champ requis
Powered by WP-Members