2012-02-27 69 views
8

我有这样的代码:Java错误:“比较方法违反其通用合同!”

package org.optimization.geneticAlgorithm; 
import org.optimization.geneticAlgorithm.selection.Pair; 

public abstract class Chromosome implements Comparable<Chromosome> { 
    public abstract double fitness(); 
    public abstract Pair<Chromosome> crossover(Chromosome parent); 
    public abstract void mutation(); 
    public int compareTo(Chromosome o) { 
     int rv = 0; 
     if (this.fitness() > o.fitness()) { 
      rv = -1; 
     } else if (this.fitness() < o.fitness()) { 
      rv = 1; 
     } 
     return rv; 
    } 
} 

每次我运行此代码时我得到这个错误:

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract! 
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:835) 
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:453) 
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376) 
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182) 
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146) 
at java.util.Arrays.sort(Arrays.java:472) 
at java.util.Collections.sort(Collections.java:155) 
at org.optimization.geneticAlgorithm.GeneticAlgorithm.nextGeneration(GeneticAlgorithm.java:74) 
at org.optimization.geneticAlgorithm.GeneticAlgorithm.execute(GeneticAlgorithm.java:40) 
at test.newData.InferenceModel.main(InferenceModel.java:134) 

我用OpenJDK7u3和我回到0时,对象是相等的。有人可以向我解释这个错误吗?

+2

无论在同一个对象上调用多少次,你的'fitness()'方法总是返回相同的值吗?你可以与我们分享实施吗? – 2012-02-27 17:27:33

回答

8

您可以进入这种情况下,如果您有任何NaN值:

例如:

public class Test 
{ 
    public static void main(String[] args) { 
     double a = Double.NaN; 
     double b = Double.NaN; 
     double c = 5; 

     System.out.println(a < b); 
     System.out.println(a > b); 
     System.out.println(b < c); 
     System.out.println(c < b); 
    } 
} 

这些打印false的所有。所以你最终可能会遇到这样的情况:两个非NaN值都被认为与NaN“相等”,但是一个比另一个更大。基本上,你应该弄清楚你想如何处理NaN值。还要检查确实是这个问题,当然......你是否真的想让NaN值适合你的健身?

+3

您可能不希望'NaN'值,但FYI'int Double.compare(double,double)'将执行满足比较器合同的比较。如Javadoc中所指定的那样,使用此比较,“NaN”值将与所有其他值进行比较,并进行比较。 – 2012-02-27 18:51:03

0

您应该尝试添加if (this == o) return 0; 因为必须返回相同的对象。

4

最大的可能是你的健身功能被打破,在以下两种方法之一:

  1. 它并不总是返回相同的值在同一对象上调用时。
  2. 它可能会返回NaN。正如Jon Skeet所解释的,您的compareTo()在存在NaN时不是传递性的。

你可以使用Double.compare()重写你的比较功能:

public int compareTo(Chromosome o) { 
    return Double.compare(o.fitness(), this.fitness()); 
} 

这需要更少的代码和需要照顾的情况(NaN的,负零等)。当然,这些角落案件是否应该首先出现是由你来决定和解决的。

相关问题