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

我有像Person这样的自定义类:

public class Person { int age; String name; } 

现在我想根据agePerson类对象进行排序。

所以我将使用Comparable接口并实现compareTo()方法。

并且比较将有基于age比较人物对象的逻辑。

所以,如果我这样做:

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

我会根据age得到排序人名单。

但我在某处读到,当我们进行Comparable实现时,我们也需要重写equals()方法。

但我现在还没有看到它的使用。

任何人都可以解释,如果我想根据age sort ,还需要覆盖equals()方法吗?

没有法律将Comparable.compareTo()equals() 。 但是我要说,如果compaeTo()返回0equals()返回false则会compaeTo()感到困惑。

我认为在你的情况下你应该使用自定义比较器而不是使你的类Comparable 。 原因是今天你的比较标准是年龄,明天它将是人的名字,然后是姓氏,然后是重量……等等。这就是引入Comparator器的原因以及应该使用它的用例。

来自可Comparable的javadoc:

强烈建议(尽管不是必需的)自然排序[即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的Class只覆盖compareTo()方法而不是equals()方法,那么我们可以有一个方案compareTo()方法返回0,但equals()方法返回false,这是非常奇怪和不一致。 假设我有一个Name类,如下所示: –

 public class Name implements Comparable { 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 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链接: – Comparator和equals()