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)
- Créer une classe
Product{sku, label, price, rating}
(égalité sursku
). - Implémenter
Comparable
pour un ordre naturel : rating décroissant, puis prix croissant, puis label. - Écrire 2
Comparator
:- a) par prix croissant puis rating décroissant,
- b) par label, insensible à la casse.
- 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.