2012-02-27 36 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的,負零等)。當然,這些角落案件是否應該首先出現是由你來決定和解決的。

相關問題