[英]How to switch sorting order in TreeSet
我有一个自定义类,在该类中我已经实现了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
构造函数。
您的身边存在一个误解:
Comparable
类具有可以相互比较的对象(例如,要对其进行排序的容器 Comparator
是比较某个类的两个对象的东西。 有没有必要为你让你的类实现两者 。
更糟糕的是:请记住,代码传达了意图:您的类实现了两个接口的想法,但是以“相反”的方式实现,这非常违反直觉 。 它只会使您的读者感到困惑,并可能导致各种错误,仅因为您的代码所做的事情很少有经验的Java开发人员会期望这样做。 切勿编写使读者感到惊讶的代码(不好的方式)。
相反,请注意,您可以简单地使用例如Collections.reverseOrder()
创建TreeSet! 换句话说:您定义了如何比较Test
两个对象的事实使您已经可以使用默认的(反向)比较器。
长话短说:避免“发明”“聪明”的技巧来解决框架行为。 相反,学习框架如何“滴答”,并适应它。 不要抗拒潮流,顺其自然。
与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());
如果使用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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.