Comparable et Comparator en Java sont très utiles pour trier une collection d’objets. Java fournit des méthodes intégrées pour trier un tableau de types primitifs ou de classes Wrapper, ou une liste. Ici, nous allons d’abord apprendre comment trier un tableau/une liste de types primitifs et de classes Wrapper, puis nous utiliserons les interfaces java.lang.Comparable et java.util.Comparator pour trier un tableau/une liste de classes personnalisées. Voyons comment nous pouvons trier un tableau/une liste de types primitifs ou d’objets avec un programme simple.
package com.journaldev.sort;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class JavaObjectSorting {
/**
* This class shows how to sort primitive arrays,
* Wrapper classes Object Arrays
* @param args
*/
public static void main(String[] args) {
//tri d'un tableau de types primitifs comme un tableau d'entiers
int[] intArr = {5,9,1,10};
Arrays.sort(intArr);
System.out.println(Arrays.toString(intArr));
//tri d'un tableau de chaînes de caractères
String[] strArr = {"A", "C", "B", "Z", "E"};
Arrays.sort(strArr);
System.out.println(Arrays.toString(strArr));
//tri d'une liste d'objets de classes Wrapper
List strList = new ArrayList();
strList.add("A");
strList.add("C");
strList.add("B");
strList.add("Z");
strList.add("E");
Collections.sort(strList);
for(String str: strList) System.out.print(" "+str);
}
}
La sortie du programme ci-dessus est :
[1, 5, 9, 10]
[A, B, C, E, Z]
A B C E Z
Maintenant, essayons de trier un tableau d’objets.
package com.journaldev.sort;
public class Employee {
private int id;
private String name;
private int age;
private long salary;
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public long getSalary() {
return salary;
}
public Employee(int id, String name, int age, int salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
//cette méthode est redéfinie pour afficher des informations conviviales sur l'employé
public String toString() {
return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
this.salary + "]";
}
}
Voici le code que j’ai utilisé pour trier le tableau d’objets Employee.
//tri d'un tableau d'objets
Employee[] empArr = new Employee[4];
empArr[0] = new Employee(10, "Mikey", 25, 10000);
empArr[1] = new Employee(20, "Arun", 29, 20000);
empArr[2] = new Employee(5, "Lisa", 35, 5000);
empArr[3] = new Employee(1, "Pankaj", 32, 50000);
//tri d'un tableau d'employés en utilisant l'implémentation de l'interface Comparable
Arrays.sort(empArr);
System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));
Lorsque j’ai essayé d’exécuter cela, cela a généré l’exception d’exécution suivante.
Exception in thread "main" java.lang.ClassCastException: com.journaldev.sort.Employee cannot be cast to java.lang.Comparable
at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at com.journaldev.sort.JavaSorting.main(JavaSorting.java:41)
Comparable et Comparator
Java fournit l’interface Comparable qui doit être implémentée par toute classe personnalisée si nous voulons utiliser les méthodes de tri des tableaux Arrays ou des collections Collections. L’interface Comparable a la méthode compareTo(T obj) qui est utilisée par les méthodes de tri, vous pouvez vérifier n’importe quelle classe Wrapper, String ou Date pour confirmer cela. Nous devons remplacer cette méthode de manière à ce qu’elle renvoie un entier négatif, zéro ou un entier positif si l’objet « this » est inférieur, égal ou supérieur à l’objet passé en argument. Après avoir implémenté l’interface Comparable dans la classe Employé, voici la classe Employé résultante.
package com.journaldev.sort;
import java.util.Comparator;
public class Employee implements Comparable {
private int id;
private String name;
private int age;
private long salary;
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public long getSalary() {
return salary;
}
public Employee(int id, String name, int age, int salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public int compareTo(Employee emp) {
//trions les employés en fonction de leur identifiant par ordre croissant
//renvoie un entier négatif, zéro ou un entier positif correspondant à l'identifiant de cet employé
//est inférieur, égal ou supérieur à l'objet spécifié.
return (this.id - emp.id);
}
@Override
//cela est nécessaire pour afficher des informations conviviales sur l'Employé
public String toString() {
return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
this.salary + "]";
}
}
Maintenant, lorsque nous exécutons le code ci-dessus pour trier les employés avec Arrays et l’afficher, voici le résultat.
Default Sorting of Employees list:
[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]
Comme vous pouvez le voir, le tableau des employés est trié par ID par ordre croissant. Cependant, dans la plupart des scénarios réels, nous voulons trier en fonction de différents paramètres. Par exemple, en tant que PDG, je voudrais trier les employés en fonction de leur salaire, tandis qu’un responsable des ressources humaines voudrait les trier par âge. C’est dans cette situation que nous avons besoin d’utiliser l’interface Java Comparator, car l’implémentation de la méthode Comparable.compareTo(Object o) peut fournir un tri par défaut et nous ne pouvons pas le changer dynamiquement. Avec Comparator, nous pouvons définir plusieurs méthodes avec différentes façons de trier, puis choisir la méthode de tri en fonction de nos besoins.
Java Comparator
L’interface Comparator compare(Object o1, Object o2) doit être implémentée et prend deux arguments de type Object. Elle doit être implémentée de manière à renvoyer une valeur entière négative si le premier argument est inférieur au deuxième, zéro s’ils sont égaux, et une valeur entière positive si le premier argument est supérieur au deuxième. Les interfaces Comparable et Comparator utilisent les génériques pour la vérification des types lors de la compilation, en savoir plus sur les Génériques Java. Voici comment nous pouvons créer différentes implémentations de Comparator dans la classe Employee.
/**
* Comparator to sort employees list or array in order of Salary
*/
public static Comparator<Employee> SalaryComparator = new Comparator<Employee>() {
@Override
public int compare(Employee e1, Employee e2) {
return (int) (e1.getSalary() - e2.getSalary());
}
};
/**
* Comparator to sort employees list or array in order of Age
*/
public static Comparator<Employee> AgeComparator = new Comparator<Employee>() {
@Override
public int compare(Employee e1, Employee e2) {
return e1.getAge() - e2.getAge();
}
};
/**
* Comparator to sort employees list or array in order of Name
*/
public static Comparator<Employee> NameComparator = new Comparator<Employee>() {
@Override
public int compare(Employee e1, Employee e2) {
return e1.getName().compareTo(e2.getName());
}
};
Toutes les mises en œuvre ci-dessus de l’interface Comparator sont des classes anonymes. Nous pouvons utiliser ces comparateurs pour passer un argument à la fonction de tri des classes Arrays et Collections.
//trier le tableau d'employés en utilisant Comparator par Salaire
Arrays.sort(empArr, Employee.SalaryComparator);
System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));
//trier le tableau d'employés en utilisant Comparator par Age
Arrays.sort(empArr, Employee.AgeComparator);
System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));
//trier le tableau d'employés en utilisant Comparator par Nom
Arrays.sort(empArr, Employee.NameComparator);
System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));
Voici la sortie du fragment de code ci-dessus:
Employees list sorted by Salary:
[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by Age:
[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
Employees list sorted by Name:
[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]
Maintenant, nous savons que si nous voulons trier un tableau d’objets java ou une liste, nous devons mettre en œuvre l’interface Comparable de java pour fournir un tri par défaut et nous devons mettre en œuvre l’interface Comparator de java pour fournir différentes manières de trier. Nous pouvons également créer une classe séparée qui met en œuvre l’interface Comparator
et ensuite l’utiliser. Voici les classes finales que nous avons expliquant Comparable et Comparator en Java.
package com.journaldev.sort;
import java.util.Comparator;
public class Employee implements Comparable {
private int id;
private String name;
private int age;
private long salary;
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public long getSalary() {
return salary;
}
public Employee(int id, String name, int age, int salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public int compareTo(Employee emp) {
//trions l'employé en fonction d'un id dans un ordre croissant
//renvoie un entier négatif, zéro, ou un entier positif comme cet identifiant d'employé
//est inférieur, égal, ou supérieur à l'objet spécifié.
return (this.id - emp.id);
}
@Override
//ceci est nécessaire pour imprimer les informations conviviales sur l'Employé
public String toString() {
return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
this.salary + "]";
}
/**
* Comparator to sort employees list or array in order of Salary
*/
public static Comparator SalaryComparator = new Comparator() {
@Override
public int compare(Employee e1, Employee e2) {
return (int) (e1.getSalary() - e2.getSalary());
}
};
/**
* Comparator to sort employees list or array in order of Age
*/
public static Comparator AgeComparator = new Comparator() {
@Override
public int compare(Employee e1, Employee e2) {
return e1.getAge() - e2.getAge();
}
};
/**
* Comparator to sort employees list or array in order of Name
*/
public static Comparator NameComparator = new Comparator() {
@Override
public int compare(Employee e1, Employee e2) {
return e1.getName().compareTo(e2.getName());
}
};
}
Voici la mise en œuvre de classe séparée de l’interface Comparator qui comparer deux objets Employés d’abord sur leur id et s’ils sont les mêmes alors sur le nom.
package com.journaldev.sort;
import java.util.Comparator;
public class EmployeeComparatorByIdAndName implements Comparator<Employee> {
@Override
public int compare(Employee o1, Employee o2) {
int flag = o1.getId() - o2.getId();
if(flag==0) flag = o1.getName().compareTo(o2.getName());
return flag;
}
}
Voici la classe de test où nous utilisons différentes façons de trier les Objets en java en utilisant Comparable et Comparator.
package com.journaldev.sort;
import java.util.Arrays;
public class JavaObjectSorting {
/**
* This class shows how to sort custom objects array/list
* implementing Comparable and Comparator interfaces
* @param args
*/
public static void main(String[] args) {
//tri tableau d'objet personnalisé
Employee[] empArr = new Employee[4];
empArr[0] = new Employee(10, "Mikey", 25, 10000);
empArr[1] = new Employee(20, "Arun", 29, 20000);
empArr[2] = new Employee(5, "Lisa", 35, 5000);
empArr[3] = new Employee(1, "Pankaj", 32, 50000);
//tri tableau employés en utilisant l'implémentation de l'interface Comparable
Arrays.sort(empArr);
System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));
//trie tableau employés en utilisant le Comparator par Salaire
Arrays.sort(empArr, Employee.SalaryComparator);
System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));
//trie tableau employés en utilisant le Comparator par Âge
Arrays.sort(empArr, Employee.AgeComparator);
System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));
//trie tableau employés en utilisant le Comparator par Nom
Arrays.sort(empArr, Employee.NameComparator);
System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));
//Liste des employés triés par ID puis par nom en utilisant la classe Comparator
empArr[0] = new Employee(1, "Mikey", 25, 10000);
Arrays.sort(empArr, new EmployeeComparatorByIdAndName());
System.out.println("Employees list sorted by ID and Name:\n"+Arrays.toString(empArr));
}
}
Voici le résultat du programme ci-dessus:
Default Sorting of Employees list:
[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]
Employees list sorted by Salary:
[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by Age:
[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
Employees list sorted by Name:
[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by ID and Name:
[[id=1, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000]]
Les interfaces java.lang.Comparable et java.util.Comparator sont des interfaces puissantes qui peuvent être utilisées pour trier des objets en Java.
Comparable vs Comparator
- L’interface Comparable peut être utilisée pour fournir un seul moyen de trier tandis que l’interface Comparator est utilisée pour fournir différentes façons de trier.
- Pour utiliser Comparable, la classe doit l’implémenter, tandis que pour utiliser Comparator, nous n’avons pas besoin de modifier la classe.
- L’interface Comparable se trouve dans le package
java.lang
, tandis que l’interface Comparator est présente dans le packagejava.util
. - Nous n’avons pas besoin de modifier le code côté client pour utiliser Comparable, les méthodes
Arrays.sort()
ouCollection.sort()
utilisent automatiquement la méthodecompareTo()
de la classe. Pour Comparator, le client doit fournir la classe Comparator à utiliser dans la méthode compare().
Savez-vous que la méthode Collections.sort() qui prend un argument Comparator suit le pattern Stratégie?
Vous pouvez consulter le code complet et plus d’exemples de base Java depuis notre Dépôt GitHub.
Source:
https://www.digitalocean.com/community/tutorials/comparable-and-comparator-in-java-example