2014-12-06 81 views
1

一切似乎都运行良好(几天),但我碰到一个问题只有一次,并有一个非常困难的时间来重现问题。 “Java 7 - “比较方法违反其总合约!”

”比较方法违反其总合同!“被抛出,完全让我措手不及。我有以下几点:

public class CustomComparator implements Comparator<Chromosome> { 

public int compare(Chromosome c1, Chromosome c2){ 

    return c1.compareTo(c2); 
} 

} 

我的染色体类:

public class Chromosome implements Comparable<Chromosome>{ 

private double rank; 

//bunch of methods... 

@Override public int compareTo(Chromosome c){ 

    final int BEFORE = -1; 
    final int EQUAL = 0; 
    final int AFTER = 1; 

    if (this.getRank() == c.getRank()) //getRank() simply returns a double value 'rank' 
     return EQUAL; 

    else if (this.getRank() < c.getRank()) 
      return BEFORE; 

    else //i.e. (this.getRank() > c.getRank()) 
     return AFTER; 

} 

我有一个ArrayList和我同时使用Collections.sort(MYLIST)和Collections.sort(MYLIST,Collections.reverseOrder()) 。到目前为止他们仍然工作得很好。我只在100次运行中遇到过这种错误。这个实现有什么问题吗?

+1

是否有任何双值的NaN? – 2014-12-06 13:29:00

+0

可能是'0.0/0.0'或类似的结果。 – 2014-12-06 13:30:31

+2

你的compareTo方法可以简单地说,'return Double.compare(this.rank,c.rank);'。自定义比较器自从它在染色体实例上调用'compareTo'时就没用了。 – 2014-12-06 13:31:06

回答

3

Java 7已经改变了他们的排序算法的行为。如果检测到违反compareTo方法的一般合同,他们现在会抛出异常。您可以阅读关于该合同的属性,例如here

一般来说它可以被侵犯,例如在的情况下,这将解决一个< B和B <一个。如果这是在Java 7之前检测到的,那么它就会被默默地忽略。现在将抛出一个异常。

如果你想使用旧的行为,您可以使用以下方法:

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

但我不鼓励你这样做。您只需通过Double.compare(a, b)将您的实现更改为双比较的标准实现。此实现正确处理双精度的无穷大和NaN值。

此外,如果您的Comparator只是代表compareTo方法,它通常可以被丢弃。

+0

谢谢。我只是使用Double.compare()来代替。我没有再次遇到这个问题,所以这很奇怪。 另外,我不确定我是否理解违反合同的例子。我怎么能有两个双值a和b,使得a wFateem 2014-12-07 16:43:18

+1

@wFateem这只是一个如何被违犯的例子。实际上还有其他几条规则必须遵循。例如对称之一。 a == a应该总是如此。但是定义双打如何工作的IEEE 754标准指出Double.NaN应该是!= Double.NaN,这违背了对称规则。这是Double.compare(...)修复的问题之一。 – noone 2014-12-07 17:53:31

+0

非常感谢您的澄清。欣赏它 – wFateem 2014-12-08 13:24:04

2

可能是你的一个参数可能是由于正或负无穷,即被零除。也不要在double值上依赖==。您应该只使用:

return Double.compare(this.getRank(), c.getRank()); 
+0

感谢您使用Double.compare()的提示,而不是使用它。 它不能成为零除的问题。 Rank是基于图像像素值(int在0和255之间)的神经网络返回的值。神经网络使用S形函数。 – wFateem 2014-12-07 16:40:03

+0

很高兴帮助。请接受答案来关闭此问题,以便可以帮助其他人解决类似问题。 – SMA 2014-12-07 16:41:29

相关问题