簡體   English   中英

在Java中實現比較器接口

[英]Implementing the comparator interface in java

在用Java實現Comparator接口時,是否需要重寫equals方法? 如果我不這樣做,Java編譯器不會抱怨。 但是可以嗎?

Comparator<T>是一個對象,可以幫助比較兩個T類型的對象。 您需要實現的唯一方法是compare(o1, o2) 它指定類T對象的順序。
出於一致性(和邏輯)的考慮,如果比較器的compare()方法在比較兩個對象o1o2時返回0 ,則o1.equals(o2)o2.equals(o1)應該返回true,但這不需要重寫equals方法。

Javadoc: 比較器

Comparator<SomeClass>接口被實現為SomeClass類的單獨類。 不需要SomeClass.equals(Object)與比較器一致。 (實際上,這將使擁有單獨的比較器對象的目的大打折扣!)

另一方面,如果SomeClass實現Comparable<SomeClass> ,則強烈建議 equals(Object)compare(SomeClass, SomeClass)保持一致。 Comparable的javadoc這樣說:

“強烈建議(盡管不是必需的)自然排序與equals保持一致。之所以這樣,是因為沒有顯式比較器的排序集(和排序映射)與自然排序為的元素(或鍵)一起使用時,表現為“奇怪”特別是,這樣的排序集(或排序映射)違反了根據equals方法定義的集合(或映射)的一般約定。”

“例如,如果一個人將兩個鍵a和b相加,使得(!a.equals(b) && a.compareTo(b) == 0)到不使用顯式比較器的排序集中,則第二個相加操作返回false(並且排序集的大小不會增加),因為從排序集的角度來看,a和b是等效的。”


如果我不這樣做,Java編譯器不會抱怨。

Java編譯器無法確定equalscompare是否一致。 (或者equalshashcode 。)從理論上講,在所有情況下都不可能做到這一點,而且在實踐中超出了“最新技術水平”。 在某些情況下,覆蓋了equals的簡單測試會發出錯誤的警告。

您不能依靠編譯器指出應用程序中的邏輯錯誤。


如果問題實際上是關於Comparable<T>.equals(Object)的語義的,那么答案在javadocs中:

“請注意,始終不要覆蓋Object.equals(Object)始終是安全的。但是,在某些情況下,重寫此方法可以通過允許程序確定兩個不同的比較器施加相同的順序來提高性能。”


特德·霍普(Ted Hopp)因此評論:

“實際上,比較器對於排序很有用;使它與equals()保持一致不會“破壞目的”是沒有道理的。通常,使它們保持一致是一個好主意,盡管這不是必需的。”

首先,Ted誤解了我寫的內容。 我說:

“它...” (即T.equals(Object)和Comparator.compare(T,T)`之間的一致性的假設要求“ ...將使擁有一個單獨的比較器的目的無效

其次,比較器與均等值一致既不是好主意,也不是壞主意。 它完全取決於equals的預期語義以及比較器的預期目的。

  • 如果比較器用於對TreeSet中的元素進行排序,則與equals不一致將導致奇怪的行為。

  • 如果比較器用於排序對象列表以進行顯示,則與equals一致性可能無關緊要。

比較器接口中此方法的JavaDoc說:“請注意,始終不要覆蓋Object.equals(Object)始終是安全的。但是,在某些情況下,重寫此方法可以通過允許程序確定兩個不同的比較器來提高性能。施加相同的命令。”

具體來說,請注意, equals()方法用於將不同的Comparator與您的Comparator實現進行比較,而不是檢查模板類型的兩個對象是否相等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM