[英]Why equals() is there is Comparator but not in Comparable interface in Java
[英]equals method contract with comparable interface
我有一個像Person這樣的自定義類:
public class Person {
int age;
String name;
}
現在,我想根據age
對Person
類對象進行排序。
因此,我將使用Comparable
接口並實現compareTo()
方法。
compareTo
將具有根據age
來比較人對象的邏輯。
所以,如果我這樣做:
Collections.sort(list); // where list is a list of person
我將根據age
獲得分類的人員清單。
但是我讀過某個地方,當我們執行Comparable
實現時,我們也需要重寫equals()
方法。
但到目前為止,我還沒有看到它的用途。
誰能解釋,如果我只想根據age
sort
,那么在哪里也需要重寫equals()
方法?
沒有法律將Comparable.compareTo()
和equals()
。 但是我會說,如果compaeTo()
返回0
而equals()
返回false
,則會造成混亂。
我認為在您的情況下,應該使用自定義比較器,而不是使您的類為Comparable
。 原因是今天您的比較標准是年齡,明天將是該人的名字,姓氏,體重等等。等等。這就是引入Comparator
的原因以及何時使用它的用例。 。
從javadoc中獲取Comparable
:
強烈建議(盡管不是必需)自然排序(即
Comparable.compareTo
定義的排序)應與equals保持一致。 之所以如此,是因為沒有顯式比較器的排序集(和排序映射)與自然排序與等式不一致的元素(或鍵)一起使用時,其行為“奇怪”。 特別是,這樣的排序集(或排序圖)違反了根據equals方法定義的集合(或圖)的一般約定。
“與equals一致”意味着,當且僅當equals
返回true
, compareTo
返回0。 因此,除非compareTo
始終為兩個不同的對象引用返回值!= 0
,否則應重寫equals
。
您不需要重寫equals,因為Collections.sort()
將使用compareTo()
,而不是equals()
。 但是,通常最好將其覆蓋。
為了對此進行詳細說明,為什么compareTo()和equals()需要保持一致。 Sorted Set取決於Object的compareTo()方法,以了解是否可以在集合中添加特定元素,並避免將重復的元素添加到集合中。 因此,如果是這種情況,則會導致歧義(從規格中復制):
例如,如果將兩個鍵a和b相加,使得(!a.equals(b)&& a.compareTo(b)== 0)到不使用顯式比較器的排序集中,則第二個add操作返回false (而且排序集的大小不會增加),因為從排序集的角度來看,a和b是等效的。
更詳細地說,排序集使用compareTo()來檢查a和b兩個元素是否相等,並且a和b的類是否僅覆蓋compareTo()方法,而不是equals()方法,那么我們可以得出一個場景其中compareTo()方法返回0,但是equals()方法返回false,這很奇怪且不一致。 假設我有一個Name類,如下所示:
public class Name implements Comparable<Name> {
private final String firstName, lastName;
public Name(String firstName, String lastName) {
if (firstName == null || lastName == null)
throw new NullPointerException();
this.firstName = firstName;
this.lastName = lastName;
}
public String firstName() {
return firstName;
}
public String lastName() {
return lastName;
}
/*public boolean equals(Object o) {
if (!(o instanceof Name))
return false;
Name n = (Name) o;
return n.firstName.equals(firstName) && n.lastName.equals(lastName);
}
public int hashCode() {
return 31 * firstName.hashCode() + lastName.hashCode();
}*/
public String toString() {
return firstName + " " + lastName;
}
public int compareTo(Name n) {
int lastCmp = n.lastName.compareTo(lastName);
return (lastCmp != 0 ? lastCmp : n.firstName.compareTo(firstName));
}
}
// Tester class main method has the below code
Name n1 = new Name("John", "Smith");
Name n2 = new Name("John", "Smith");
SortedSet<Name> mySet = new TreeSet<>();
System.out.println(mySet.add(n1));
System.out.println(n1.equals(n2));
System.out.println(n1.compareTo(n2));
System.out.println(mySet.add(n2));
輸出如下所示:
true
false
0
false
現在這顯示出歧義,因為我們還沒有覆蓋equals()在這種情況下返回false,但是compareTo()返回0,因此SortedSet認為兩個對象n1和n2相等,因此將n2添加到Set中返回false如sysout中所示,但它們不相等!!!
有關更多信息,請參考stackoverflow鏈接:- 比較器和equals()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.