Dex*_*ter 2 java sorting collections comparable
我试图在Java中为一个对象实现类似的接口,我需要通过两个不同的列/变量进行排序.我尝试了多种方法,到目前为止这是最好的方法:
public int compareTo(Object o) {
Match m = (Match)o;
int diff = m.matches - matches;
if (diff == 0) {
if (distance > m.distance) {
return 1;
} else if (distance < m.distance) {
return -1;
} else {
return 0;
}
} else {
return diff;
}
}
Run Code Online (Sandbox Code Playgroud)
但它仍然失败了
java.lang.IllegalArgumentException: Comparison method violates its general contract!
Run Code Online (Sandbox Code Playgroud)
我有什么想法我做错了吗?
附注1:如果o为null或不合适的类,则需要NPE/ClassCastExceptions - 这不是问题.
旁注2:我知道JDK 1.7中排序算法的变化,但我真的没有看到我在这里违反合同的地方.所以关闭异常似乎是错误的解决方案.
既然你说distance是双重的,你可能会遇到如下所述的相同问题:
也许:
public int compareTo(Object o) {
Match m = (Match)o;
int diff = m.matches - matches;
if (diff == 0) {
return Double.compare(distance, m.distance);
} else {
return diff;
}
}
Run Code Online (Sandbox Code Playgroud)
但理想情况下,您应该使用内置的比较方法,如下所述.上面的代码是"需要的最小变化"的一个例子,说明了关键问题.
另外,正如@ fabian-barney在答案中指出的那样,你应该避免直接的区别,而是利用内置的比较方法.所以你应该有类似的东西:
public int compareTo(Object o) {
Match m = (Match) o;
return m.matches == matches ? Double.compare(m.distance, distance) : Integer.compare(m.matches, matches);
}
Run Code Online (Sandbox Code Playgroud)
这样,Double.compare将为您处理NaN值.对于任何数字x(NaN除外)Double.compare(x, Double.NaN) == -1将返回true(即,NaN被认为大于任何其他数字).
这里注意,你都OK使用==与int秒,但它是更为复杂与double因Double.NaN != Double.NaN.但是,new Double(Double.NaN).equals(Double.NaN)是的.请参阅为什么Java的Double.compare(double,double)实现方式如何?一个很好的讨论.
要查看如果您有NaN,原始实现可能会破坏合同的示例,请参阅Java compareTo文档.我们有:
最后,实现者必须确保x.compareTo(y)== 0意味着对于所有z,sgn(x.compareTo(z))== sgn(y.compareTo(z)).
所以,想象一下你有x = NaN和y = 5和z = 6,则:
x.compareTo(y) == 0(因为NaN > 5并且NaN < 5是假的)x.compareTo(z) == 0 (同样的推理)y.compareTo(z) == -1 (y <z).所以2和3(+ sgn)不是必需的.
| 归档时间: |
|
| 查看次数: |
986 次 |
| 最近记录: |