我有一个自定义类,在该类中我已经实现了Comparable
和Comparator
接口。两者的排序/比较逻辑相反。
以下面的类为例:
class Test implements Comparable<Test>, Comparator<Test>{
private Integer field;
public Test(Integer field){this.field = field;}
@Override
public int compareTo(Test obj){
return this.field.compareTo(obj.field);
}
@Override
public int compare(Test t1, Test t2){
return -t1.compareTo(t2);
}
//impl of equals, hashCode and toString omitted for this example
}
因此,默认情况下,当我将Test
的对象添加到TreeSet
时,它是根据Comparable
的实现进行排序的,根据JDK源代码的理解。那么,是否有任何标志/开关可以切换到Comparable
实现所表示的排序?
我不想将另一个Comparator
传递给TreeSet
构造函数。
答案 0 :(得分:3)
您身边有一个误解:
Comparable
类具有可以相互比较的对象(例如,要对其进行排序的容器Comparator
是用于比较某个类的两个对象的东西。您无需使类都实现为两者。
更糟糕的是:请记住,代码传达了意图:您的类同时实现了两个接口的想法,但是以“相反”的方式实现了反直观。它只会使您的读者感到困惑,并可能导致各种错误,仅因为您的代码所做的事情很少有经验的Java开发人员会期望这样做。永远不要写让读者惊讶的代码(不好的方式)。
请注意,例如,您可以简单地使用Collections.reverseOrder()
创建TreeSet!换句话说:您定义了如何比较Test
的两个对象这一事实,使您已经可以使用默认的(reversing)比较器。
答案 1 :(得分:0)
使用与Comparator
和Comparable
相同的对象是非常不典型的。您可以仅使用两个接口之一来实现两个排序顺序。
仅Comparator
:
//Test implements Comparator. reversed() changes order
new TreeSet(new Test().reversed());
仅Comparable
:
//elements are Comparable. reverseOrder changes order
new TreeSet(Comparator.reverseOrder());
答案 2 :(得分:0)
如果使用Comparator.comparingInt(Test::getField).reversed())
,则不需要为Test类实现自己的比较方法。
完整的示例代码:
static class Test {
private int field;
public Test(int field) {
this.field = field;
}
public int getField() {
return field;
}
}
public static void main(String[] args) {
Test test = new Test(5);
Test test2 = new Test(8);
TreeSet<Test> tests = new TreeSet<>(Comparator.comparingInt(Test::getField).reversed());
tests.add(test);
tests.add(test2);
for (Test t:tests)
System.out.println(t.getField());
}
输出:
8
5