2012-02-27 23 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()'メソッドは、同じオブジェクトに対して何回呼び出されても、常に同じ値を返しますか?実装を私たちと共有できますか? –

答えて

8

あなたはそのような状況の中に得ることができます。したがって、NaN以外の2つの値が両方ともNaNと「等しい」とみなされていたが、一方が他方よりも大きい状況に終わる可能性があります。基本的には、NaN値をどのように処理するかを検討する必要があります。それが本当に問題であることを確認してください。もちろん、あなたのフィットネスのNaN値が本当に必要ですか?

+3

おそらく 'NaN'の値は望ましくありませんが、FYI、' int Double.compare(double、double) 'はコンパレータ契約を満たす比較を行います。 Javadocで指定されているように、この比較を使用して、「NaN」の値は他のすべての値と等しいかそれ以上の値と比較されます。 –

0

if (this == o) return 0; を追加する必要があります。同じオブジェクトを同じにする必要があるためです。例えば

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値を持っている場合

4

おそらくあなたの適性の機能は、次のいずれかの方法で、壊れている:

  1. 同じオブジェクト上で呼び出されたときにそれは常に同じ値を返しません。
  2. NaNを返す可能性があります。 compareTo()は、Naonの存在下で推移的ではありません。これについては、Jon Skeetによって説明されています。

あなたはDouble.compare()を使用して、比較関数を書き換えることができます:

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

これは、より少ないコードを必要とし、コーナーケース(NaNを、負のゼロなど)の世話をします。もちろん、これらのコーナーケースが最初に発生するかどうかは、あなたが決定して対処することです。

関連する問題