如果compareTo()返回0,为什么暗示对象相等?

让我们上一堂课Person。人有名字和身高。

Equals和hashCode()仅考虑名称。人是可比的(或者我们为它实现比较器,没有关系)。将人按身高进行比较。

预期两个不同的人可以具有相同的身高的情况似乎是合理的,但是例如。TreeSet的行为就像comapareTo()== 0意味着相等,而不仅仅是相同的大小。

为避免这种情况,如果大小相同,比较可以次之于别的东西,但是它不能用于检测相同大小的不同对象。

例:

import java.util.Comparator;

import java.util.HashSet;

import java.util.Objects;

import java.util.Set;

import java.util.TreeSet;

public class Person implements Comparable<Person> {

private final String name;

private int height;

public Person(String name,

int height) {

this.name = name;

this.height = height;

}

public int getHeight() {

return height;

}

public void setHeight(int height) {

this.height = height;

}

public String getName() {

return name;

}

@Override

public int compareTo(Person o) {

return Integer.compare(height, o.height);

}

public boolean equals(Object obj) {

if (obj == null) {

return false;

}

if (getClass() != obj.getClass()) {

return false;

}

final Person other = (Person) obj;

if (!Objects.equals(this.name, other.name)) {

return false;

}

return true;

}

public int hashCode() {

int hash = 5;

hash = 13 * hash + Objects.hashCode(this.name);

return hash;

}

public String toString() {

return "Person{" + name + ", height = " + height + '}';

}

public static class PComparator1 implements Comparator<Person> {

@Override

public int compare(Person o1,

Person o2) {

return o1.compareTo(o2);

}

}

public static class PComparator2 implements Comparator<Person> {

@Override

public int compare(Person o1,

Person o2) {

int r = Integer.compare(o1.height, o2.height);

return r == 0 ? o1.name.compareTo(o2.name) : r;

}

}

public static void test(Set<Person> ps) {

ps.add(new Person("Ann", 150));

ps.add(new Person("Jane", 150));

ps.add(new Person("John", 180));

System.out.println(ps.getClass().getName());

for (Person p : ps) {

System.out.println(" " + p);

}

}

public static void main(String[] args) {

test(new HashSet<Person>());

test(new TreeSet<Person>());

test(new TreeSet<>(new PComparator1()));

test(new TreeSet<>(new PComparator2()));

}

}

结果:

java.util.HashSet

Person{Ann, height = 150}

Person{John, height = 180}

Person{Jane, height = 150}

java.util.TreeSet

Person{Ann, height = 150}

Person{John, height = 180}

java.util.TreeSet

Person{Ann, height = 150}

Person{John, height = 180}

java.util.TreeSet

Person{Ann, height = 150}

Person{Jane, height = 150}

Person{John, height = 180}

你知道为什么会这样吗?

回答:

java.util.SortedSetjavadoc中提取:

请注意,如果排序集要正确实现Set接口,则排序集(无论是否提供显式比较器)所维护的顺序必须与equals一致。(有关与equals一致的精确定义,请参见Comparable接口或Comparator接口。)之所以这样,是因为Set接口是根据equals操作定义的,但是排序后的set使用其compareTo(或compare)方法执行所有元素比较。

,因此从排序集的角度来看,此方法认为相等的两个元素相等。即使排序顺序与equals不一致,也可以很好地定义排序集的行为。它只是不遵守Set接口的一般约定。

因此,换言之,SortedSet破坏(或“扩展”)了Object.equals()和的一般合同Comparable.compareTo。参见合同compareTo

强烈建议(但并非严格要求(x.compareTo(y)==

0)==(x.equals(y))。一般而言,任何实现Comparable接口且违反此条件的类都应明确指出这一事实。推荐的语言是“注意:此类具有与等式不一致的自然顺序”。

以上是 如果compareTo()返回0,为什么暗示对象相等? 的全部内容, 来源链接: utcz.com/qa/433387.html

回到顶部