有人可以說明compareTo()
與類的equals()
不一致時的後果。我已經讀過,如果Obj1.compareTo(Obj2) = 0
那麼它不是強制性的是Obj1.equals(Obj2) = true
。但是如果發生這種情況會有什麼後果。謝謝。當compareTo()與equals()不一致時的後果
回答
爲Comparable
文檔解釋了這個在一些細節:
一類
C
的自然順序被認爲是與equals
當且僅當e1.compareTo(e2) == 0
對每一個e1
相同的布爾值e1.equals(e2)
一致,e2
類別C
。請注意,null
不是任何類的實例,並且e.compareTo(null)
應拋出NullPointerException
,即使e.equals(null)
返回false
。強烈建議(儘管不要求)自然排序與
equals
一致。這是因爲,如果排序集(和排序映射)沒有顯式比較器,當它們與自然排序與equals
不一致的元素(或鍵)一起使用時,其行爲會「奇怪」。特別是,這樣一個有序的集合(或有序的映射)違反了集合(或映射)的一般合約,這是根據equals
方法定義的。例如,如果加上兩個鍵
a
和b
使得(!a.equals(b) && a.compareTo(b) == 0)
到有序集合不使用顯式的比較器,第二個加法操作返回false
(有序集合不增加的大小)因爲a
和b
等同於排序集的視角。實際上,實現
Comparable
的幾乎所有Java核心類都具有與equals
一致的自然排序。一個例外是java.math.BigDecimal
,其自然排序等於BigDecimal
具有相同值和不同精度的對象(如4.0
和4.00
)。
比較'compareTo'與'equals'不一致的例子:http://stackoverflow.com/questions/12587896/customizing-the-get-method-in-hashmap/12588005#12588005 – assylias 2013-03-22 14:42:19
@NPE你能不能請解釋一下這個「特別是,這樣一個有序集合(或排序映射)違反了集合(或映射)的一般契約,這是用等價方法定義的。」舉一個例子。我無法正確地得到它。謝謝。 – Trying 2013-03-22 14:42:35
@Trying:從Set的文檔:*集合不包含元素e1和e2的對,使得e1.equals(e2)*。另一方面,'SortedSet'(它必須完成這個合約,因爲它是一個'Set')使用'compareTo()'而不是'equals()'。因此,如果你的對象不一致地實現'compareTo/equals',並且把它們放在一個'SortedSet'中,那麼你就會迫使後者違反合同。 – NPE 2013-03-22 14:53:00
一些收藏會假設如果兩個物體跟隨obj1.compareTo(obj2) = 0
然後obj1.equals(obj2)
也是如此。例如:排序爲TreeSet
。 未能符合此邏輯將導致圖標一致的集合。參見: Comparator and equals()。
儘管文檔說明一致性不是強制性的,但最好始終確保一致性,因爲您永遠不知道您的對象是否會在TreeMap
/TreeSet
之類的某一天出現。如果compareTo()
對於不相等的2個對象返回0,則所有基於Tree的集合都將被打破。
例如,假設一類Query
,執行一個SQL查詢,有2場:
- tableList:表
- 參考清單:使用這樣的查詢程序列表
假設兩個對象在它們的tableList相等時是相等的,即tableList
是這個對象的天然關鍵。 hashCode()
和equals()
只考慮現場tableList
:
public class Query implements Comparable {
List<String> tableList;
List<String> references;
Query(List<String> tableList, List<String> references) {
this.tableList = tableList;
this.references = references;
Collections.sort(tableList); // normalize
}
@Override
public int hashCode() {
int hash = 5;
hash = 53 * hash + Objects.hashCode(this.tableList);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Query other = (Query) obj;
return Objects.equals(this.tableList, other.tableList);
}
}
比方說,我們想排序是沿着引用的數量。 天真地編寫代碼產生了compareTo()
方法,這可能是這樣的:
public int compareTo(Object o) {
Query other = (Query) o;
int s1 = references.size();
int s2 = other.references.size();
if (s1 == s2) {
return 0;
}
return s1 - s2;
}
這樣做似乎平等確定和排序是在兩個不同的領域完成的,越遠越好。
但是,無論何時放入TreeSet
或TreeMap
,都是災難性的:這些類的實現認爲如果compareTo返回0,則元素相等。在這種情況下,這意味着具有相同參考數量的每個對象確實是「相等的」對象,顯然不是這種情況。
更好compareTo()
方法可能是:
public int compareTo(Object o) {
Query other = (Query) o;
// important to match equals!!!
if (this.equals(other)) {
return 0;
}
int s1 = references.size();
int s2 = other.references.size();
if (s1 == s2) {
return -1; // not 0, they are NOT equal!
}
return s1 - s2;
}
- 1. java float:== equals compareTo
- 2. equals和compareTo是否有意義不一致?
- 3. java.util.concurrent.Delayed是否真的迫使我違反equals/compareTo一致性?
- 4. treemap使用compareTo而不是equals for containsKey()
- 5. BigDecimal的equals()方法對的compareTo()
- 6. 使用比較器聚合類似的對象與equals()不一致equals()
- 7. Should.js - equals方法中的不一致should.equals
- 8. 爪哇可比對象equals()和鑑於employee1的compareTo()返回不同的結果
- 9. 如何有一個TreeSet「與equals不一致」
- 10. C#/ Java:正確實施CompareTo當Equals測試參考身份
- 11. 與pkgutil.iter_modules結果不一致
- 12. CompareTo與Equals!比較字符串或對象?
- 13. 如何重寫equals(),hashCode()和的compareTo()對於一個HashSet
- 14. ==,CompareTo()和Equals()不同意會發生什麼?
- 15. 兩個「==」操作和equals/compareTo方法不工作
- 16. Android Studio .compareTo和.equals字符串不工作
- 17. MySQL與Date()的結果不一致()select
- 18. 與java線程不一致的結果
- 19. 與Grep不一致的結果
- 20. 驅動api:file.list當corpus ='user'時返回不一致的結果
- 21. 爲什麼Int16.CompareTo從Int32返回不同的結果.CompareTo
- 22. 喬達時間 - 不一致的結果
- 23. 當活動被殺時與OnActivityResult()的行爲不一致
- 24. 當MVC中的結果不一致時,SQL返回兩次相同的結果
- 25. compareTo導致堆棧溢出
- 26. 與的compareTo()方法
- 27. 的equals()VS的compareTo()比較器/能(理論)
- 28. 結果不一致與隨機列表
- 29. Java併發性:與結果不一致
- 30. 與輸出結果不一致
除非你做一個 – 2013-03-22 14:30:10
@Sam我,你才能取悅更多煞費苦心。 – Trying 2013-03-22 14:31:19
這個問題非常模糊。結果是「如果你用兩種不同的方式比較它們,你會得到兩個不同的答案」 - 後續結果取決於你爲什麼要進行比較。 – 2013-03-22 14:32:07