2017-05-23 42 views
0

我在嘗試對節點的數組列表進行排序時出現此錯誤。我嘗試了大多數解決方案,但是沒有一個適用於我的情況。JAVA_Runtime_Error: - 比較方法違反了其總體合同

java.lang.IllegalArgumentException: Comparison method violates its general contract! 
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:866) 
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:483) 
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:406) 
at java.util.ComparableTimSort.sort(ComparableTimSort.java:213) 
at java.util.Arrays.sort(Arrays.java:1312) 
at java.util.Arrays.sort(Arrays.java:1506) 
at java.util.ArrayList.sort(ArrayList.java:1454) 
at j... 

代碼,這是

static class Node implements Comparable<Node> 
{ 
    int key; 
    int value; 
    int double_value; 

    public Node(int key , int value , int double_value) 
    { 
     this.key = key; 
     this.value = value; 
     this.double_value = double_value; 
    } 

    public int compareTo(Node node) 
    { 
     if(double_value < node.double_value) 
      return 1; 
     else if(double_value > node.double_value) 
      return -1; 

     return -1; 
    } 
} 

它適用於小的投入,但是當輸入的數量是很大它給這個錯誤。我也在比較方法中閱讀了傳遞性規則,但我無法弄清楚在這種情況下它是如何應用的。

在此先感謝。

+1

返回-1,如果兩個節點具有相同的值,這意味着根據您比較的順序,節點可以同時小於並大於其他節點。這實際上違反了「Comparable.compareTo」的合同(就此而言常識也被違反)。對於比較雙倍的簡單情況,請改爲使用'Double.compare'方法。 –

+2

你的'compareTo'永遠不會返回'0'來表明它們是相同的,你也應該重寫'equals()',這樣兩個節點持有相同的double_value'n1.equals(n2)'返回true。當你重寫equals時,你應該重寫'hashcode()' –

+0

請不要下劃線!遵循Java命名約定並用'doubleValue'替換'double_value'。 –

回答

2

因爲實際上比較int值(儘管它被命名 _value),你可以有一個非常簡單的compareTo方法

public int compareTo(Node node) 
{ 
    return this.double_value - node.double_value; 
} 

您不必返回-1,0,或+ 1 - 任何負值或正值都可以。
的文檔compareTo()說:

比較此對象與指定對象的順序。返回負整數,零或正整數,因爲此對象小於,等於或大於指定的對象。

所以

Node node1 = new Node(5, 5, 5); 
Node node2 = new Node(7, 7, 7); 
System.out.println(node1.compareTo(node2)); 

會產生-2,因爲5是小於7

當你覆蓋的compareTo你也應該覆蓋.equals(Node other),當你重寫等於你應該also override hashCode()


更新每克里斯·帕克的評論更好的安全性,這要追溯到使用-1,0,1結果:

public int compareTo(Node other) 
{ 
    final long m = (long) this.double_value = (long) other.double_value; 
    return m < 0 ? -1 : 
      m > 0 ? 1 : 
      0; 
} 
+1

謹慎使用減法進行比較。根據所包含的數字,您可以超過帶符號的32位整數的值,並且溢出將導致無效返回。 –

+0

@Chris這是真的......你最終可能會得到'Integer.MIN_VALUE - Integer.MAX_VALUE',它不正確地出現爲'1'。你可以擴大範圍,比如'long m =(long)a - (long)b;'使它更安全。 –

相關問題