2013-01-18 40 views
1

在android應用程序中,我有一個位置列表。我需要根據他們與用戶位置的距離對它們進行排序。爲此我實現了一個自定義比較器:此自定義比較方法是否包含邏輯錯誤

Collections.sort(houseList, new Comparator<HouseEntity>() 
    { 
    @Override 
    public int compare(HouseEntity house1, HouseEntity house2) 
    { 
     if(userLocation == null) return 0; 
     return (int) (userLocation.distanceTo(house1.location) - userLocation.distanceTo(house2.location)); 
    } 
    }); 

它在我所做的所有測試中運行良好。但是,有些用戶曾與以下錯誤崩潰:

java.lang.IllegalArgumentException: Comparison method violates its general contract! 

閱讀上的所有其他同樣的問題後,所以我的結論是,當有可能是邏輯錯誤(例如,我們可能會得到一個>出現這個錯誤b和b> a)。但是我找不到任何場景來複制那個邏輯錯誤。

什麼情況可能導致此錯誤?我該如何解決它?

非常感謝您的幫助

+2

你確定轉換成'(int)'永遠不會溢出/下溢嗎?你可以嘗試'Double.compare(x,y)'而不是? –

+0

您是否嘗試過記錄比較結果? 「distanceTo」方法的返回類型是什麼? –

+0

看來,在這些情況下,一些不良的值被傳入? – shuangwhywhy

回答

1

由於彼得Lawrey說,你應該使用Double.compare(x, y)Float.compare(x, y)代替鑄造爲int。這裏的解釋:

比較必須是傳遞的,即只要A == B和B == C,那麼也A == C.讓我們想象一下,我們有三點ABC與距離用戶位置0.2,0.4和1.3。

  1. (INT)(0.2 - 0.4)=(int)的(-0.2)= 0 =>A == B
  2. (INT)(0.4 - 1.3)=(int)的(-0.9)= 0 =>B == C
  3. (INT)(0.2 - 1.3)=(int)的(-1.1)= -1 =>A < C

正如你可以看到比較器是不傳遞的。

+0

謝謝你,這正是錯誤的地方 – Youssef

0

如果userLocation == null然後house1.equals(house2)應該給予正確的。

+0

這並沒有真正回答這個問題。 –

+1

用給定的錯誤消息拋出的'IllegalArgumentException'指示'compare'方法與'equals'方法不一致。我指出了這種情況,當這種情況發生時,但直到我們看到'HouseEntity.equals()'的實現時,我們確實無法確定這是否是原因。 –