Published by: Stephane, Last edited
Dans cet article nous verrons comment utiliser les interfaces Comparator et Comparable avec la méthode sort() de la classe Collections pour trier les objets d'une liste (ArrayList ou List) dans un ordre croissant ou décroissant à partir d’un ou de plusieurs critère(s) déterminé(s). On verra également la différence entre ces deux interfaces et quand utiliser l’une ou l’autre.
Problème : Dans notre salle de classe nous avons des étudiants que nous désirons classer par ordre d’âge croissant. Comment si prendre ? Nous aimerions également par la suite les classer suivant leur moyenne annuelle et leur nom Que faire ?
A. Utilisation de l’interface Comparable pour comparer suivant un seul critère
L’interface comparable facilite la comparaison des objets suivant un critère connue d’avance. Dans notre cas on désire comparer les étudiants suivant leur âge.
Cette interface a une seule méthode abstraite compareTo() qui accepte un objet en paramètre et retourne un nombre entier (int).
@Override
public int compareTo(Etudiant etudiant) {
if(etudiant == null) // Linge #n1
return -1;
return this.age - etudiant.age; // Linge #n2
}
La première étape (ligne #n1) consiste à s’assurer que l’objet reçu en paramètre n’est pas null.
La deuxième étape c’est la comparaison à proprement parlé (ligne #n2). Pour cela on fait la différence d’âge entre l’étudiant actuel (this) et celui reçu en paramètre. En effectuant la différence dans cet ordre on obtient un classement par ordre d’âge croissant et ainsi, si l’âge de l’étudiant actuel (this) est supérieur à celui de l’étudiant reçu en paramètre un nombre positif est retourné signifiant que l’âge de l’étudiant actuel est supérieur à celui reçu en paramètre. Un nombre négatif sera retourné dans le cas contraire signifiant que l’étudiant reçu en paramètre à un âge supérieur à celui de l’étudiant actuel (this). Si on désire obtenir ce classement par ordre d’âge décroissant on peut effectuer une différence inverse :
return etudiant.age – this.age;
Contrairement à l’interface Comparator qu’on verra plus bas, l’interface Comparable est faite pour être implémentée par la classe dont on veut effectuer les comparaisons.
Limite de l’interface Comparable
Cette interface est peu flexible car elle limite la comparaison suivant un seul critère connu au préalable. Qu’en sera-t-il lorsque nous désirerons comparer les mêmes élèves suivant leur moyenne annuelle ou suivant l’ordre alphabétique du nom ? ça devient compliqué n’est-ce pas ?
Comparator au secours !!! ☺.
B. Utilisation de l’interface Comparator pour comparer suivant différents critères
Explication
L’interface Comparator contient également une seule méthode abstraite compare() qui accepte deux objets à comparer en paramètre.
Cette interface n’est pas implémentée par la classe à comparer et peut être utilisée de différentes manières.
// Ligne #n3 Utilisation d'une classe anonyme
Comparator comparerParMoyenne = new Comparator() {
@Override
public int compare(Etudiant etudiant1, Etudiant etudiant2) {
return etudiant1.getMoyenneAnnuelle() - etudiant2.getMoyenneAnnuelle();
}
};
//Ligne #n5. Utilisation d'une fonction lambda et delegation
//de la comparaison à la methode compareTo de la classe String
Comparator comparerParNom =
(etudiant1, etudiant2) -> etudiant1.getPrenom().compareTo(etudiant2.getPrenom());
Conclusion
Nous sommes arrivé au terme de cet article où nous avons vu comment comparer et trier des objet en Java en utilisation les interfaces Comparable et Comparator en plus de la méthode sort() de la classe Collections. J’espère que vous l’avez trouvé intéressant et qu’il vous aidera à écrire du code meilleur.
Si vous avez des questions ou commentaires n’hésitez pas à me contacter sur twitter ou LinkedIn. Merci de partager avec d’autres personnes si vous l’avez trouvé intéressant.
Closing Tip: Il est vivement encouragé qu'à chaque fois que vous implémentez l’interface comparable, qu’il y ait une consistance entre les méthodes equal() et compareTo(). En d’autre terme il faut s’assurer qu’à chaque fois que x.equals(y) retourne “true”, que x.compareTo(y) retourne 0.