Interface Comparator
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 45 sur 87.
Alors que Comparable définit l'ordre naturel d'une classe, vous avez parfois besoin de trier des objets de différentes manières. L'interface Comparator vous permet de créer une logique de comparaison distincte sans modifier la classe d'origine.
Un Comparator est un objet externe qui compare deux objets du même type. C'est utile lorsque vous voulez plusieurs options de tri ou quand vous ne pouvez pas modifier la classe elle-même :
import java.util.Comparator;
class NameComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
}
class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}Vous pouvez ensuite passer le comparateur aux méthodes de tri :
List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 30));
people.add(new Person("Alice", 25));
Collections.sort(people, new NameComparator()); // Trié par nom
Collections.sort(people, new AgeComparator()); // Trié par âgePour un code concis, vous pouvez utiliser des expressions lambda puisque Comparator est une interface fonctionnelle :
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));La différence clé : Comparable est implémentée par la classe comparée et définit un ordre naturel, tandis que Comparator est une classe distincte qui peut définir un nombre illimité d'ordres personnalisés.
Défi
FacileConstruisons un système de tri d'employés qui démontre la puissance de l'interface Comparator. Vous allez créer plusieurs comparateurs pour trier les employés de différentes manières — par salaire et par nom — sans modifier la classe Employee elle-même.
Vous organiserez votre code sur quatre fichiers :
Employee.java: Créez une classe représentant un employé avec trois champs privés :name(String),department(String), etsalary(double). Incluez un constructeur pour initialiser tous les champs et des méthodes getter pour chacun. SurchargeztoString()pour retourner :[name] ([department]) - $[salary]SalaryComparator.java: Créez un comparateur qui trie les employés par salaire par ordre décroissant (le plus haut salaire en premier). Implémentez l'interfaceComparator<Employee>et sa méthodecompare(). UtilisezDouble.compare()pour une comparaison sécurisée des valeurs de salaire.NameComparator.java: Créez un autre comparateur qui trie les employés par ordre alphabétique par nom par ordre croissant (de A à Z). ImplémentezComparator<Employee>et utilisez la méthodecompareTo()de la classe String pour la comparaison.Main.java: Rassemblez le tout en créant une liste d'employés et en les triant à l'aide de vos comparateurs. Vous recevrez en entrée les données de trois employés, chacun sur une ligne séparée au format :name,department,salaryCréez une
ArrayListd'employés, puis démontrez les deux approches de tri :- D'abord, triez par salaire en utilisant votre
SalaryComparatoret affichez chaque employé - Affichez une ligne vide
- Ensuite, triez par nom en utilisant votre
NameComparatoret affichez chaque employé
- D'abord, triez par salaire en utilisant votre
Vous recevrez trois lignes d'entrée, chacune contenant les données d'un employé au format : name,department,salary
Par exemple, une ligne d'entrée pourrait ressembler à : Alice,Engineering,75000.0
N'oubliez pas d'importer java.util.Comparator dans vos fichiers de comparateurs, et java.util.ArrayList, java.util.Collections, et java.util.Scanner dans votre fichier Main. Remarquez comment les comparateurs vous permettent de définir plusieurs stratégies de tri de manière externe — la classe Employee n'a pas besoin de savoir comment elle pourrait être triée !
Aide-mémoire
L'interface Comparator vous permet de créer une logique de comparaison externe pour trier des objets sans modifier la classe d'origine. C'est utile lorsque vous avez besoin de plusieurs options de tri.
Un Comparator compare deux objets du même type en implémentant la méthode compare() :
import java.util.Comparator;
class NameComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
}Passez le comparateur aux méthodes de tri :
Collections.sort(people, new NameComparator());Vous pouvez utiliser des expressions lambda pour un code plus concis puisque Comparator est une interface fonctionnelle :
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));Pour comparer des valeurs numériques, utilisez les méthodes des classes wrappers comme Double.compare() pour une comparaison sécurisée :
class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}Différence clé : Comparable définit un ordre naturel unique au sein de la classe elle-même, tandis que Comparator est une classe distincte qui peut définir un nombre illimité d'ordres personnalisés de manière externe.
Essayez vous-même
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lire trois employés à partir de l'entrée
// Format de chaque ligne : name,department,salary
String line1 = scanner.nextLine();
String line2 = scanner.nextLine();
String line3 = scanner.nextLine();
// TODO: Analyser chaque ligne et créer des objets Employee
// Hint: Utiliser split(",") pour séparer les valeurs
// TODO: Créer une ArrayList d'employés et ajouter les trois
// TODO: Trier par salaire en utilisant SalaryComparator et afficher chaque employé
// Hint: Utiliser Collections.sort(list, comparator)
// TODO: Afficher une ligne vide
// TODO: Trier par nom en utilisant NameComparator et afficher chaque employé
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron Itérateur