Trier un ArrayList d'objets avec Comparable et Comparator

Dans ce tutoriel, on va voir comment faire le tri d'un ArrayList qui contient des objets à l'aide des deux interfaces java.lang.Comparable et java.util.Comparator. Si votre programme nécessite le tri d'un ArrayList de String ou de Integer, il vaut mieux consulter ces deux articles:

- Trier un ArrayList de type String ou Integer
- Trier un ArrayList dans l'ordre décroissant

L'interface Comparable est utilisé lorsqu'on veut trier une liste d'objets en comparant deux objets avec la méthode prédéfinie objet1.compareTo(object2).

Trier un ArrayList en utilisant Comparable

Avant, laissons-nous voir le résultat de tri d'un arraylist d'objets sans implémenter l'interface Comparable.

Créons une classe Employe.java:

public class Employe {

private String nom;
private int age;
private long salaire;

public String getName() {
return nom;
}

public int getAge() {
return age;
}

public long getSalary() {
return salaire;
}

public Employe(String nom, int age, int salaire) {
this.nom = nom;
this.age = age;
this.salaire = salaire;
}

@Override
//cette méthode affiche les informations de l'employé
public String toString() {
return "[nom=" + this.nom + ", age=" + this.age + ", salaire=" +
this.salaire + "]";
}
}
On veut créer une liste d'objets ArrayList<Employe>:

import java.util.ArrayList;
import java.util.Collections;

public class ArrayListComparable {

public static void main(String[] args) {
ArrayList<Employe> arraylist = new ArrayList<Employe>();
arraylist.add(new Employe("mateo", 32, 20000));
arraylist.add(new Employe("katia", 26, 10000));
arraylist.add(new Employe("aline", 30, 40000));
arraylist.add(new Employe("salim", 28, 35000));

System.out.println("liste ordonnée des employés:\n"+Collections.sort(arraylist));
}
}
L'appel de la méthode Collections.sort() cause problème car il se fait sur un ArrayList d'objets qui ne marche pas à moins qu'on utilise les deux interfaces Comparable et Comparator. Une erreur de compilation s'affiche:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
The operator + is undefined for the argument type(s) String, void
Bound mismatch: The generic method sort(List) of type Collections is not applicable for the arguments (ArrayList). The inferred type Employe is not a valid substitute for the bounded parameter >

at ArrayListComparable.main(ArrayListComparable.java:14)

Maintenant, vous devez avoir compris l'importance de ces deux interfaces.

Disons qu'on veut trier la liste selon la propriété: salaire de l'employé. Cela est peut être fait en implémentant l'interface Comparable, puis java fait une comparaison automatique avec la méthode compareTo()déclarée Override.

Après l'implémentation de l'interface Comparable dans la classe Employe.java, voici le résultat:

public class Employe implements Comparable<Employe>{

private String nom;
private int age;
private long salaire;

public String getName() {
return nom;
}

public int getAge() {
return age;
}

public long getSalary() {
return salaire;
}

public Employe(String nom, int age, int salaire) {
this.nom = nom;
this.age = age;
this.salaire = salaire;
}

@Override
//cette méthode affiche les informations de l'employé
public String toString() {
return "[nom=" + this.nom + ", age=" + this.age + ", salaire=" +
this.salaire + "]";
}

@Override
public int compareTo(Employe emp) {
//trions les employés selon leur age dans l'ordre croiddant
//retroune un entier négative, zéro ou positive si l'age
//de cet employé est moins que, égale à ou supérieur à l'objet comparé avec
return (this.age - emp.age);
}
}
Maintenant, on a le droit d'appeler la méthode Collections.sort():

import java.util.ArrayList;
import java.util.Collections;

public class ArrayListComparable {

public static void main(String[] args) {
ArrayList<Employe> arraylist = new ArrayList<Employe>();

arraylist.add(new Employe("mateo", 32, 20000));
arraylist.add(new Employe("katia", 26, 10000));
arraylist.add(new Employe("aline", 30, 40000));
arraylist.add(new Employe("salim", 28, 35000));

Collections.sort(arraylist);

System.out.println("liste ordonnée des employés selon l'age:\n");
for(Employe e:arraylist)
System.out.println(e);
}
}
Quand on exécute ce morceau de code on aura le résultat suivant:

liste ordonnée des employés par age:

[nom=katia, age=26, salaire=10000]
[nom=salim, age=28, salaire=35000]
[nom=aline, age=30, salaire=40000]
[nom=mateo, age=32, salaire=20000]

Trier un ArrayList en utilisant Comparator

Comme vous voyez, la liste des employés ci-dessus est triée dans l'ordre croissant. mais pourquoi utiliser l'interface Comparator alors ? Parce qu'il y aura peut être des situations dont le tri est basé sur plusieurs paramètres contrairement à Comparable. Par exemple, on veut bien que le tri des employés soit basé sur le nom, l'age et le salaire.

La méthode compare(Object o1, Object o2) de l'interface Comparator prend deux objets. Dans notre exemple, elle doit être implémentée trois fois (nom, age et salaire) de manière qu'elle retourne un entier négative si le premier argument est plus petit que que le deuxième et zéro s'ils sont égaux et un entier positive si le premier argument est plus grand que que le deuxième.

import java.util.Comparator;

public class Employe {

private String nom;
private int age;
private long salaire;

public String getNom() {
return nom;
}

public int getAge() {
return age;
}

public long getSalaire() {
return salaire;
}

public Employe(String nom, int age, int salaire) {
this.nom = nom;
this.age = age;
this.salaire = salaire;
}

@Override
//cette méthode affiche les informations de l'employé
public String toString() {
return "[nom=" + this.nom + ", age=" + this.age + ", salaire=" +
this.salaire + "]";
}

/*
* Comparator pour le tri des employés par nom
*/
public static Comparator<Employe> ComparatorNom = new Comparator<Employe>() {

@Override
public int compare(Employe e1, Employe e2) {
return e1.getNom().compareTo(e2.getNom());
}
};
/*
* Comparator pour le tri des employés par age
*/
public static Comparator<Employe> ComparatorAge = new Comparator<Employe>() {

@Override
public int compare(Employe e1, Employe e2) {
return (int) (e1.getAge() - e2.getAge());
}
};
/*
* Comparator pour le tri des employés par salaire
*/
public static Comparator<Employe> ComparatorSalaire = new Comparator<Employe>() {

@Override
public int compare(Employe e1, Employe e2) {
return (int) (e1.getSalaire() - e2.getSalaire());
}
};
}
La classe de test main:

import java.util.ArrayList;
import java.util.Collections;

public class main{

public static void main(String[] args) {
ArrayList<Employe> arraylist = new ArrayList<Employe>();

arraylist.add(new Employe("mateo", 32, 20000));
arraylist.add(new Employe("katia", 26, 10000));
arraylist.add(new Employe("aline", 30, 40000));
arraylist.add(new Employe("salim", 28, 35000));

//tri par nom
Collections.sort(arraylist, Employe.ComparatorNom);

System.out.println("liste ordonnée des employés par nom:");
for(Employe e:arraylist)
System.out.println(e);

//tri par age
Collections.sort(arraylist, Employe.ComparatorAge);

System.out.println("liste ordonnée des employés par age:");
for(Employe e:arraylist)
System.out.println(e);

//tri par salaire
Collections.sort(arraylist, Employe.ComparatorSalaire);

System.out.println("liste ordonnée des employés par salaire:");
for(Employe e:arraylist)
System.out.println(e);
}
}
L'exécution de ce code donne:

liste ordonnée des employés par nom:
[nom=aline, age=30, salaire=40000]
[nom=katia, age=26, salaire=10000]
[nom=mateo, age=32, salaire=20000]
[nom=salim, age=28, salaire=35000]
liste ordonnée des employés par age:
[nom=katia, age=26, salaire=10000]
[nom=salim, age=28, salaire=35000]
[nom=aline, age=30, salaire=40000]
[nom=mateo, age=32, salaire=20000]
liste ordonnée des employés par salaire:
[nom=katia, age=26, salaire=10000]
[nom=mateo, age=32, salaire=20000]
[nom=salim, age=28, salaire=35000]
[nom=aline, age=30, salaire=40000]