Technologies et Applications d'entreprise

Java/Jee XML Webservices SOA

Posted on by Rabii


Incontournable si vous passez un entretien technique ou si vous comptez passez prochainement votre SCJP, les interfaces Comparator et Comparable sont à connaitre. C'est quoi la différence entre ces deux interfaces ? Comment pouvons-nous les utiliser ?

Dans cet article on va discuter de java.util.Comparator et java.lang. Comparable en détailles avec quelques exemples pour des précisions supplémentaires.

C'est quoi Comparator et Comparable ?

Comparator et Comparable en Java sont deux parmi les interfaces fondamentale de l'API Java qui sont très important à comprendre pour mettre en œuvre le tri en Java. Il est souvent nécessaire de trier des objets stockés dans des collection ou dans des tableaux, et là  nous aurons besoin d'utiliser compare () et compareTo. Ces méthodes sont définies dans java.util.Comparator et java.lang.Comparable. Voyons quelques points importants concernant à la fois comparable et Comparator  avant d'aller plus loi.

Comparable

Un objet comparable est capable de se comparer avec un autre objet. La classe elle-même doit implémenter  l'interface java.lang.Comparable afin d'être en mesure de comparer ses instances. Les classes qui implémentent cette interface peuvent être trié facilement dans les collections comme on peut voir dans l’exemple ci dessous :

package com.ben.nasr.fr.collections;

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

public class TriCollections {

/**
* @param args
*/
public static void main(String[] args) {

ListmaListe = new ArrayList();
maListe.add(19);
maListe.add(3);
maListe.add(7);
maListe.add(12);
maListe.add(71);
maListe.add(10);
System.out.println("Before");
for (Integer integer : maListe) {
System.out.println(integer);
}
// ce ci est possible car les objet dans la liste sont de type integer
// la class Integr implemente l'interface comparable,
// donc on peut comparer les instances de cette classe
Collections.sort(maListe);
System.out.println("After");

for (Integer integer : maListe) {
System.out.println(integer);
}
}

}

D'autres class en java implémente comparable comme (Byte, Short, Integer, Long, Float, Double, BigInteger, BigDecimal,String, Date..) et peuvent ainsi
être trié facilement selon l'ordre naturel définis.

Tri en utilisant Comparable

Si on veut que notre class possèdent un ordre naturel à son tour on doit implémenter Comparable.

Afin de pouvoir comparer les objet on doit implémenter la méthode compareTo dans notre class. On doit s'assurer à l'implémentation que cette méthode respecte certains règles :

  1. c1.compareTo(c2) retourne un entier negative (si c1<c2), zéro si c1=c2, ou un entier positive si c1>c2.
  2. Doit lancer une "ClassCastException " si les c1 et c2 ne sont pas comparables.
  3. Doit lancer une "NullPointerException " si c2 est null.

Dans notre exemple on a une class Client et on veut sauvegarder quelques instances de cette class dans une liste dans l'ordre ascendant selon leur Nom. Voici la class Client ainsi qu'une autre classe qui teste l'ordre :


package com.ben.nasr.fr.comparable.comparator;

import java.util.Date;

public class Client implements Comparable<Client> {

private int clientId;
private String clientNom;
private double prixCommande;
private Date dateFirstCommande;
public Client() {
}

public Client(int clientId, String clientNom, double prixCommande, Date dateFirstCommande) {
this.clientId = clientId;
this.clientNom = clientNom;
this.prixCommande = prixCommande;
this.dateFirstCommande = dateFirstCommande;
}

@Override
public int compareTo(Client client) {
if (client == null) {
throw new NullPointerException("compareTo: argument est null");
}

if (this.getClass().equals(client.getClass())) {
// deux objet comparable

Client tmp = (Client) client;
return this.getClientNom().compareTo(tmp.getClientNom());
}

else {
// deux objets pas comparable
throw new ClassCastException(
"compareTo: les deux objet peuvent pas etre comapre");
}
}

public int getClientId() {
return clientId;
}

public void setClientId(int clientId) {
this.clientId = clientId;
}

public String getClientNom() {
return clientNom;
}

public void setClientNom(String clientNom) {
this.clientNom = clientNom;
}

public double getPrixCommande() {
return prixCommande;
}

public void setPrixCommande(double prixCommande) {
this.prixCommande = prixCommande;
}

public Date getDateFirstCommande() {
return dateFirstCommande;
}

public void setDateFirstCommande(Date dateFirstCommande) {
this.dateFirstCommande = dateFirstCommande;
}

}

Notre class de test :


package com.ben.nasr.fr.comparable.comparator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

public class TestClient {
public static void main(String[] args) {

Client c1 = new Client(10,"Cedric",3000.00,new Date(2009,11,11));
Client c2 = new Client(10,"Amri",3000.00,new Date(2009,11,11));
Client c3 = new Client(10,"Tom",3000.00,new Date(2009,11,11));
Client c4 = new Client(10,"Nicolas",3000.00,new Date(2009,11,11));
Client c5 = new Client(10,"John",3000.00,new Date(2009,11,11));
Client c6 = new Client(10,"Ben",3000.00,new Date(2009,11,11));

List<Client> list = new ArrayList<Client>();
list.add(c1);
list.add(c2);
list.add(c3);
list.add(c4);
list.add(c5);
list.add(c6);
// Avant le tri
System.out.println("Avant le tri :");
System.out
.println("===============================================================");
System.out.println("ID  Nom  PrixCommande  Date First Commande");
System.out
.println("===============================================================");
for (Client client : list) {
System.out.println(client.getClientId() + "\t\t "
+ client.getClientNom() + "\t\t" + client.getPrixCommande()
+ "\t\t " + client.getDateFirstCommande().getDay() + "-"
+ client.getDateFirstCommande().getMonth() + "-"
+ client.getDateFirstCommande().getYear());
}

// Tri
Collections.sort(list);
// Apres le tri
System.out.println("\n\n Apres le Tri");
System.out
.println("===============================================================");
System.out.println("ID  Nom  PrixCommande  Date First Commande");
System.out
.println("===============================================================");
for (Client client : list) {
System.out.println(client.getClientId() + "\t\t "
+ client.getClientNom() + "\t\t" + client.getPrixCommande()
+ "\t\t " + client.getDateFirstCommande().getDay() + "-"
+ client.getDateFirstCommande().getMonth() + "-"
+ client.getDateFirstCommande().getYear());
}
}
}

Comparator

Un objet Comparator est capable de comparer deux objets différents. La classe qui implémente cette interface ne compare pas ses instances, mais les instances d'autres classes.

Imaginons maintenant qu'on veut trié nos clients selon un autre critère, on sera obligé de modifié compareTo(). Dans ce cas on va perdre le principe de tri actuel de la class. Donc cette solution n'est pas bonne si on veut faire le tri selon différent critère/attribut à différentes occasions. Un autre cas de figure se pose aussi si on n'a pas le droit de modifier la class Client, ainsi on pourra pas toucher au compareTo ni implémenter quelconque interface.C'est ici qu'intevient l'interface Comparator pour nous sauver !

En écrivant une classe qui implémente l'interface java.util.Comparator, on peut trier les clients en utilisant n'importe quel attribut que nous le souhaitons,  et cela sans toucher la classe Client lui-même.

Tri avec Comparator

Voyons comment cela est possible. On commence par écrire notre class "ClientNomComparator" :


package com.ben.nasr.fr.comparable.comparator;

import java.util.Comparator;

public class ClientNomComparator implements Comparator<Client>{

@Override
public int compare(Client e1, Client e2) {
if(e1 == null || e2 == null){
throw new NullPointerException("argument null");
}
return e1.getClientNom().compareTo(e2.getClientNom());
}

}

On peut écrire autant de class implémentant Comparator qu'on veut. Ci dessous une class comparant les clients selon leur date de première commande :


package com.ben.nasr.fr.comparable.comparator;

import java.util.Comparator;

public class ClientDatePremComComparator implements Comparator<Client> {

@Override
public int compare(Client e1, Client e2) {
if (e1 == null || e2 == null) {
throw new NullPointerException(" argument null");
}
return new Integer(e1.getDateFirstCommande().compareTo(
e2.getDateFirstCommande()));
}

}

De la même façon qu'on fait pour tester Comparable, on crée une class de Test. Ce qui change cette fois ci, est que Client n'implémente aucune interface et notre class "ClientDatePremComComparator " ou "ClientNomComparator " sera passé en argument à la fonction Sort :

// Tri de client selon leur nom
Collections.sort(list, newClientNomComparator());
// Tri de client selon leur date de premiere commande
Collections.sort(list,new ClientDatePremComComparator ());

Posted on by Rabii | Posted in Java | Tagged , , ,


About Rabii

Ingénieur d'études et de développement chez "SOAT

One Response to Comparator ou Comparable ?

  1. Paul says:


    très bon article, bien expliqué merci


Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *