Java比较器给定的属性名称进行比较

Java Comparator given the name of the property to compare

我的问题是这个;我必须订购一个数据表。表的每一行都是一个存储在List中的对象(我们称其为TableObject)。数据的每一列都是该类的属性(通常是String)。

当用户单击任何列时,我必须对数据进行典型的排序。所以我考虑过将List更改为TreeSet并在TableObject中实现Comparator。

当我尝试重新排序TreeSet时出现问题。首先比较起来很容易(省略了parseInt中的异常查找):

1
2
3
4
5
6
7
8
9
10
11
12
   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;

    }

但是当我不得不按数据的文本或TableObject具有的其他数十种数据重新排序时,我遇到了问题。
我不想创建数十个比较函数,每个比较函数一个。我宁愿不要使用开关(或ifs链)来决定如何比较对象。

是否有某种方式可以做到这一点(例如Reflexive),这并不意味着我会写成几百行几乎相同的代码?

谢谢大家!


Bean Comparator应该可以工作。

使用反射BeanComparator,将允许您对具有零参数方法的任何属性进行排序,该方法返回该属性的值。

因此,基本上,您可以对具有" getter "方法的任何属性进行排序。


您可以做的是使比较器采用String表示要在其构造函数中进行排序的参数的名称。

然后,您可以使用反射按给定的参数进行排序。

以下代码很脏。但是我认为这说明了您需要做的要点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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");
        }
    }
}


是的,您可以使用反射API根据其名称获取字段的内容。

请参见Field类,尤其是Field.get方法。

(不过,我不推荐这样做,因为反射不是针对此类任务而设计的。)