簡體   English   中英

等於具有可比較接口的方法合同

[英]equals method contract with comparable interface

我有一個像Person這樣的自定義類:

public class Person {
    int age;
    String name;
}

現在,我想根據agePerson類對象進行排序。

因此,我將使用Comparable接口並實現compareTo()方法。

compareTo將具有根據age來比較人對象的邏輯。

所以,如果我這樣做:

Collections.sort(list);  // where list is a list of person

我將根據age獲得分類的人員清單。

但是我讀過某個地方,當我們執行Comparable實現時,我們也需要重寫equals()方法。

但到目前為止,我還沒有看到它的用途。

誰能解釋,如果我只想根據age sort ,那么在哪里也需要重寫equals()方法?

沒有法律將Comparable.compareTo()equals() 但是我會說,如果compaeTo()返回0equals()返回false ,則會造成混亂。

我認為在您的情況下,應該使用自定義比較器,而不是使您的類為Comparable 原因是今天您的比較標准是年齡,明天將是該人的名字,姓氏,體重等等。等等。這就是引入Comparator的原因以及何時使用它的用例。 。

從javadoc中獲取Comparable

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

“與equals一致”意味着,當且僅當equals返回truecompareTo返回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.

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