等于具有可比接口的方法合同
我有像Person这样的自定义类:
public class Person { int age; String name; }
现在我想根据age
对Person
类对象进行排序。
所以我将使用Comparable
接口并实现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
则会compaeTo()
感到困惑。
我认为在你的情况下你应该使用自定义比较器而不是使你的类Comparable
。 原因是今天你的比较标准是年龄,明天它将是人的名字,然后是姓氏,然后是重量……等等。这就是引入Comparator
器的原因以及应该使用它的用例。
来自可Comparable
的javadoc:
强烈建议(尽管不是必需的)自然排序[即
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的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()