Written by Fneuch on 12.12.06
Vous avez une liste d'objet et vous voulez la trier sans passer par la Base de donnée. Vous ne voulez pas non plus implémenter l'interface comparable car vous ne voulez pas utiliser toujours le même tri...
Faites vous un objet Comparator!
En voici un qui tri sur une propriété de type Integer. C'est un draft pour répondre à mes besoins, mais c'est pour le principe.
package com.fneuch.collections.functor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Comparator;
public class IntegerPropertyComparator implements Comparator {
private String nomPropriete;
/**
* Constructeur par défaut.
* Ne pas oubliez d'assigner la nom de la propriété à comparer avant d'utiliser
* le comparator.
*/
public IntegerPropertyComparator() {
}
/**
* Constructeur permettant de fournir immédiatement le nom de la propriété à
* comparer.
*
* @param nomPropriete le nom de la propriété à comparer.
*/
public IntegerPropertyComparator(String nomPropriete) {
this.setNomPropriete(nomPropriete);
}
/**
* Méthode privée permettant de regrouper en un seul endroit la récupération
* de la valeur entière recherchée.
*
* @throws java.lang.reflect.InvocationTargetException Lorsque l'invocation de la méthode est infructueuse
* @throws java.lang.IllegalAccessException Si la méthode n'est pas accessible (avec un statut private par exemple)
* @throws java.lang.NoSuchMethodException Si la méthode n'existe pas
* @return la valeur entière (int) retournée par la méthode demandée
* @param obj Sur quel objet fesons nous l'invocation de la méthode.
* @param methodName Le nom de la méthode à invoquer.
*/
private int getMethodValue(String methodName, Object obj)
throws NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
// Plus claire de travailler sur l'objet classe que sur obj.getClass()
Class classe = obj.getClass();
// Récupération de la méthode à invoquer
Method method1 = classe.getMethod(methodName, new Class[] {});
// Ce comparateur ne fonctionne que sur les Integer ou les types int
// retourne en type primitif int pour des raisons de simplicité.
return ((Integer)method1.invoke(obj, new Object[] {} )).intValue();
}
/**
* Effectue la comparaison sur la méthode fournis.
*
* @return <0 si l'objet1 est plus petit, >0 si l'objet1 est plus grand et 0 si les 2 objets sont égaux
* @param o1 Le premier objet à comparer
* @param o2 Le deuxième objet à comparer
*/
public int compare(Object o1, Object o2) {
// Le nom de la propriété ne peut pas être nul ou vide
if(this.nomPropriete == null && this.nomPropriete.trim().length() == 0) {
throw new IllegalStateException("Vous devez préciser un nom de propriété à comparer");
}
/*
* Étant donné qu'on ne connait pas l'objet et qu'on fonctionne par une
* propriété pour l'instant je me limite à vérifier l'assignation.
*
* Pourrait être améliorer pour vérifier la présence de la propriété afin de
* pouvoir comparer 2 objets totalement différents, tant qu'ils ont la même
* propriété.
*/
if(!(o1.getClass().isAssignableFrom(o2.getClass()) && o2.getClass().isAssignableFrom(o1.getClass()))) {
throw new ClassCastException("Impossible de comparer " + o1.getClass().getName()
+ " avec la classe " + o2.getClass().getName());
}
// OK, on cherche une méthode du style getNomPropriete
StringBuffer sb = new StringBuffer("get");
sb.append(this.nomPropriete.substring(0,1).toUpperCase());
sb.append(this.nomPropriete.substring(1));
String methodProperty = sb.toString();
// Pour la comparaison par la suite
int valeur1 ;
int valeur2;
// Les 2 try consécutifs servent uniquement à avoir un message d'exception
// plus précis
try {
// On récupère la valeur de l'objet 1
try {
valeur1 = getMethodValue(methodProperty, o1);
} catch (NoSuchMethodException nsfe) {
throw new IllegalStateException("La propriété " + this.nomPropriete
+ " n'existe pas dans l'objet "
+ o1.getClass().getName());
}
// On récupère la valeur de l'objet 2
try {
valeur2 = getMethodValue(methodProperty, o2);
} catch (NoSuchMethodException nsfe) {
throw new IllegalStateException("La propriété " + this.nomPropriete
+ " n'existe pas dans l'objet "
+ o2.getClass().getName());
}
} catch (IllegalAccessException iae) {
throw new ClassCastException("Impossible de comparer " + o1.getClass().getName()
+ " avec la classe " + o2.getClass().getName());
} catch (InvocationTargetException ite) {
throw new ClassCastException("Impossible de comparer " + o1.getClass().getName()
+ " avec la classe " + o2.getClass().getName());
}
// On fait la comparaison et retourne le résultat
return (valeur1 - valeur2);
}
/**
* Retourne le nom de la propriété qui sera comparé.
*
* @return le nom de la propriété
*/
public String getNomPropriete() {
return nomPropriete;
}
/**
* Assigne le nom de la propriété à comparer.
*
* @param nomPropriete le nom de la propriété
*/
public void setNomPropriete(String nomPropriete) {
this.nomPropriete = nomPropriete;
}
}
Et vous l'utilisez de la façon suivante:
Collections.sort(liste,new IntegerPropertyComparator("ordreAffichage"));
Et voilà, votre objet liste sera trié.
Tout ce que vous avez à faire c'est d'avoir une
liste d'objets semblables qui contiennent la méthode
getOrdreAffichage().

| Posted in »
exemple code,
java