Sommaire
Eh oui, dans le merveilleux monde de la programmation, on est souvent amenés à trier des données. Que ce soit pour afficher une liste d’utilisateurs par ordre alphabétique, ranger nos fichiers par taille ou encore classer nos produits du moins cher au plus cher, le tri est partout ! En Java, deux interfaces sont là pour nous simplifier la vie : Comparable et Comparator . Prêt à les dompter ? Alors, c’est parti !
Comparable : la voie du moindre effort (mais pas toujours)
Commençons par Comparable , l’interface la plus simple à utiliser. Son principe ? Implémenter la méthode compareTo()
dans notre classe pour définir la logique de tri. Concrètement, on va comparer l’objet courant avec un autre objet du même type, et renvoyer un entier négatif, nul ou positif selon que l’objet est inférieur, égal ou supérieur à l’autre.
Bon, ça reste assez théorique, non ? Allez, un petit exemple pour tout éclaircir !
Exemple de tri avec Comparable
Imaginez qu’on veuille trier une liste de personnages de la série animée Les Simpson. On crée d’abord une classe Personnage
qui implémente Comparable<Personnage>
:
class Personnage implements Comparable<Personnage> {
String nom;
Personnage(String nom) {
this.nom = nom;
}
@Override
public int compareTo(Personnage autre) {
return this.nom.compareTo(autre.nom);
}
}
Ici, on trie simplement par ordre alphabétique des noms en utilisant la méthode compareTo()
de la classe String
. Pratique, non ?
Ensuite, on peut créer une liste de personnages et la trier avec la méthode Collections.sort()
:
List<Personnage> personnages = new ArrayList<>();
personnages.add(new Personnage("Homer"));
personnages.add(new Personnage("Marge"));
personnages.add(new Personnage("Bart"));
personnages.add(new Personnage("Lisa"));
Collections.sort(personnages);
for (Personnage p : personnages) {
System.out.println(p.nom);
}
Et voilà, la console affichera :
BartHomerLisaMarge
Facile, non ? Comparable est idéal quand on a un critère de tri évident et unique. Mais attention, si on veut trier selon plusieurs critères ou avec une logique plus complexe, il faudra se tourner vers Comparator.
Comparator : la flexibilité à son meilleur
Voilà, on a vu le fonctionnement de Comparable. Mais que faire si on veut trier nos personnages selon plusieurs critères, comme l’âge en plus du nom ? C’est là qu’intervient Comparator , l’interface qui nous offre une flexibilité totale !
Contrairement à Comparable, Comparator n’est pas implémenté dans la classe à trier. On crée plutôt une classe séparée qui implémente Comparator<MaClasse>
et définit la logique de tri dans la méthode compare()
.
Exemple de tri avec Comparator
Reprenons notre exemple des personnages des Simpson. Cette fois, créons une classe ComparateurPersonnage
qui implémente Comparator<Personnage>
:
class ComparateurPersonnage implements Comparator<Personnage> {
@Override
public int compare(Personnage p1, Personnage p2) {
int comparaisonNom = p1.nom.compareTo(p2.nom);
if (comparaisonNom != 0) {
return comparaisonNom;
}
return p1.age - p2.age;
}
}
Ici, on trie d’abord par ordre alphabétique des noms. S’il y a égalité, on départage en triant par âge croissant.
Pour utiliser notre Comparator, on passe une instance de ComparateurPersonnage
à la méthode Collections.sort()
:
List<Personnage> personnages = new ArrayList<>();
personnages.add(new Personnage("Homer", 39));
personnages.add(new Personnage("Marge", 36));
personnages.add(new Personnage("Bart", 10));
personnages.add(new Personnage("Lisa", 8));
Collections.sort(personnages, new ComparateurPersonnage());
for (Personnage p : personnages) {
System.out.println(p.nom + " (" + p.age + " ans)");
}
Et le résultat sera :
Bart (10 ans)Lisa (8 ans)Homer (39 ans)Marge (36 ans)
Comme vous pouvez le voir, Comparator nous offre une grande souplesse. On peut définir des critères de tri complexes, en chaîner plusieurs, ou même utiliser des lambda expressions pour plus de concision (on y reviendra).
Attention, si vous essayez de trier une liste d’objets qui n’implémentent ni Comparable ni Comparator, vous aurez droit à une jolie ClassCastException. Rien de bien méchant, mais autant éviter ce petit désagrément !
Comparable vs Comparator : lequel choisir ?
Maintenant que nous avons vu les deux interfaces en action, vous vous demandez sûrement laquelle choisir. Eh bien, tout dépend de vos besoins !
Si vous avez un critère de tri évident et unique, comme trier des chaînes de caractères par ordre alphabétique, alors Comparable est parfait. C’est simple, clair et intégré directement dans la classe. Pas besoin de code supplémentaire.
En revanche, si vous devez trier selon plusieurs critères, ou que la logique de tri est complexe ou susceptible de changer, alors Comparator est le choix judicieux. Oui, ça demande un peu plus de code, mais vous gagnerez en flexibilité et en maintenabilité.
Un exemple pour bien comprendre
Imaginez qu’on veuille trier une liste de films. Au départ, on veut les trier par ordre alphabétique de titre. Pas de problème, on implémente Comparable<Film>
dans la classe Film
.
Mais quelques mois plus tard, le client veut aussi pouvoir trier par année de sortie, ou encore par note moyenne des critiques. Avec Comparable, on devrait ajouter de nouvelles méthodes compareTo()
dans la classe Film
, ce qui deviendrait vite un joyeux bazar.
Avec Comparator, en revanche, on créerait simplement de nouvelles classes ComparateurFilmParAnnee
, ComparateurFilmParNote
, etc. Le code reste modulaire et facile à maintenir.
Bref, dans l’idéal, commencez avec Comparable pour un tri simple, et n’hésitez pas à passer à Comparator si vos besoins évoluent. Les deux interfaces sont compatibles, vous pourrez toujours réutiliser votre classe existante.
Une astuce pour bien démarrer : implémentez toujours Comparable, même si vous pensez avoir besoin de Comparator. Ça vous évitera de vous prendre la tête plus tard si vos besoins changent !
Pour conclure sur le tri en Java
Voilà, vous savez désormais tout (ou presque) sur le tri d’objets en Java avec Comparable et Comparator ! Comme vous avez pu le constater, ce ne sont pas des concepts bien compliqués. Il suffit de bien comprendre quand utiliser chaque interface, et le tour est joué.
Pour résumer en quelques mots :
- Comparable : la solution simple et directe pour un critère de tri unique.
- Comparator : la flexibilité ultime pour des critères multiples ou complexes.
Alors, prêt à ranger vos objets comme il se doit ? Un dernier conseil : n’ayez pas peur d’expérimenter ! Le tri est un concept fondamental en programmation, vous en aurez besoin tôt ou tard. Autant s’y mettre dès maintenant et bien maîtriser ces deux interfaces. Go, go, go !
Le récap’ qu’il est bien !
- Comparable permet de trier des objets selon un critère unique défini dans la classe
- Comparator offre plus de flexibilité pour trier avec des critères multiples ou complexes
- Commencez par Comparable pour un tri simple, passez à Comparator si vos besoins évoluent
- Veillez à bien implémenter l’une ou l’autre interface pour éviter les ClassCastException
- N’ayez pas peur de pratiquer, le tri est un concept crucial en programmation !