我有像Person这样的自定义类:
public class Person {
int age;
String name;
}
现在我想根据Person
对age
类对象进行排序。
所以我将使用Comparable
接口并实现compareTo()
方法。
并且compareTo
将具有基于age
比较人物对象的逻辑。
所以,如果我这样做:
Collections.sort(list); // where list is a list of person
我将根据age
获得排序人员列表。
但是我在某处读到了,当我们执行equals()
时,我们也需要覆盖Comparable
方法。
但我现在还没有看到它的使用。
任何人都可以解释一下,如果我只想基于equals()
sort
来覆盖age
方法吗?
答案 0 :(得分:7)
没有法律涉及Comparable.compareTo()
和equals()
。但是,如果compaeTo()
返回0
而equals()
返回false
,我会说这很令人困惑。
我认为在您的情况下,您应该使用自定义比较器,而不是使您的类Comparable
。原因是今天你的比较标准是年龄,明天它将是人的名字,然后是姓氏,然后是权重......等等。这就是Comparator
被引入的原因和用例的时候它应该被使用。
答案 1 :(得分:6)
来自Comparable
的javadoc:
强烈建议(尽管不要求)自然 订单[即由
Comparable.compareTo
]定义的排序与equals一致。这是因为排序集 没有显式比较器的(和排序的地图)表现得“奇怪” 它们与自然顺序的元素(或键)一起使用 与equals不一致。特别是,这样的排序集(或排序的 map)违反了定义的集合(或映射)的一般合同 就平等方法而言。
“与equals一致”表示compareTo
当且仅当equals
返回true
时才返回0。因此,除非compareTo
始终为两个不同的对象引用返回值!= 0
,否则应覆盖equals
。
答案 2 :(得分:5)
您不需要覆盖等号,因为Collections.sort()
将使用compareTo()
,而不是equals()
。但是,覆盖它通常是一个好主意。
答案 3 :(得分:2)
只是详细说明为什么compareTo()和equals()需要保持一致。 Sorted Set取决于Object的compareTo()方法,以了解是否可以在集合中添加特定元素,并避免将重复元素添加到集合中。因此,如果是这种情况,则会导致歧义(从规范中复制): -
例如,如果添加两个键a和b使得(!a.equals(b)&& a.compareTo(b)== 0)到一个不使用明确的 比较器,第二个add操作返回false(和大小 排序集不会增加)因为a和b是等价的 排序集的视角。
详细说明,排序集使用了compareTo()来检查两个元素a& b是否相等,如果是& b只覆盖compareTo()方法而不是equals()方法,那么我们可以有一个场景,其中compareTo()方法返回0,但equals()方法返回false,这是非常奇怪和不一致的。我们假设我有一个Name类,如下所示: -
proguardFiles
}
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));
现在这显示了模糊性,因为我们没有覆盖equals(),在这种情况下返回false,但compareTo()返回0,因此SortedSet认为两个对象n1和n2相等,因此添加了n2进入Set返回false,如sysout所示,但它们不相等!!!
有关详情,请参阅stackoverflow链接: - Comparator and equals()