2010-11-09 4 views
3

Mon problème est ceci; Je dois commander une table de données. Chaque ligne de la table est un objet (appelons-le TableObject) stocké dans une liste. Chaque colonne de données est une propriété de la classe (généralement une chaîne).Java Comparateur donné le nom de la propriété à comparer

Je dois faire l'ordonnancement typique des données lorsque l'utilisateur clique sur n'importe quelle colonne. J'ai donc pensé à changer la liste en TreeSet et à implémenter le comparateur dans mon TableObject.

Le problème vient quand j'essaye de réorganiser le TreeSet. La comparaison est assez facile au début (cheeking des exceptions en parseInt ont été omis):

public int compare(TableObject to1, TableObject to2){ 
     TableObject t1 = to1; 
     TableObject t2 = to2; 

     int result = 1; 

     if(Integer.parseInt(t1.getId()) == Integer.parseInt(t2.getId())){result=0;} 
     if(Integer.parseInt(t1.getId()) < Integer.parseInt(t2.getId())){result=-1;} 

     return result; 

    } 

Mais quand je dois modifier l'ordre par le texte des données ou par d'autres dizaines de données que le TableObject a j'ai problème. Je ne veux pas créer des dizaines de fonctions de comparaison, chacune pour un. Je préfère ne pas utiliser un interrupteur (ou une chaîne d'ifs) pour décider comment comparer l'objet.

Existe-t-il un moyen de le faire d'une certaine manière (comme Reflexive), cela n'implique pas que j'écrirai comme des centaines de lignes de presque le même code?

Merci pour tout!

Répondre

3

Ce que vous pouvez faire est que le comparateur prenne un String représentant le nom du paramètre à trier dans son constructeur.

Ensuite, vous pourriez utiliser la réflexion pour trier par le paramètre donné.

Le code suivant est très sale. Mais je pense que cela illustre l'essentiel de ce que vous auriez besoin de faire.

public class FieldComparator<T> implements Comparator<T> { 
    String fieldName; 

    public FieldComparator(String fieldName){ 
     this.fieldName = fieldName; 
    } 

    @Override 
    public int compare(T o1, T o2) { 
     Field toCompare = o1.getClass().getField(fieldName); 
     Object v1 = toCompare.get(o1); 
     Object v2 = toCompare.get(o2); 
     if (v1 instanceof Comparable<?> && v2 instanceof Comparable<?>){ 
      Comparable c1 = (Comparable)v1; 
      Comparable c2 = (Comparable)v2; 
      return c1.compareTo(c2); 
     }else{ 
      throw new Exception("Counld not compare by field"); 
     } 
    } 
} 
+0

Merci! Cela l'illustre très bien. J'ai essayé de le faire comme ça mais ça fait quelques années de tout programme de réflexivité ... Encore une fois, merci! – Random

+0

@Random, vous êtes les bienvenus. Heureux de vous aider. – jjnguy

+0

Je voudrais voter ceci comme correct, mais la réponse de camickr, même si ce n'est pas aussi efficace que le vôtre est plus facile et plus rapide à mettre en œuvre. Je pense que nous ne devrions pas réécrire le code qui fonctionne déjà. Même dans ce cas, je les marquerais tous les deux correctement, si je le pouvais. – Random

1

Oui, vous pouvez utiliser le reflection API, pour obtenir le contenu d'un champ en fonction de son nom.

Voir la classe Field et en particulier la méthode Field.get.

(je ne le recommanderais pas cependant, que la réflexion n'a pas été conçu pour ce type de tâche.)

+0

"la réflexion n'est pas conçue pour ce type de tâche" ... Raison de plus pour la battre et la laisser plaider dans un coin pour qu'elle reste seule. – RHSeeger

+0

bien ... Si j'ai le nom de la propriété dont j'ai besoin, alors c'est une tâche de refelction. Merci pour le Field.get Bien que mon projet soit en Java 5 ... – Random

+0

Je ne suis pas d'accord. À partir de la toute première page du [Parcours de réflexion] (http://download.oracle.com/javase/tutorial/reflect/index.html), vous pouvez lire * "La réflexion est puissante, mais ne doit pas être utilisée sans discernement. est possible d'effectuer une opération sans utiliser de réflexion, alors il est préférable d'éviter de l'utiliser. "* – aioobe

Questions connexes