如果compareTo()返回0,为什么暗示对象相等? [英] Why it is implied that objects are equal if compareTo() returns 0?

查看:905
本文介绍了如果compareTo()返回0,为什么暗示对象相等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let's have a class Person. Person has a name and height.

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

Equals and hashCode() takes into account only name. Person is comparable (or we implement comparator for it, does not matter which one). Persons are compared by height.

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

It seems reasonable to expect a situation where two different persons can have same height, but eg. TreeSet behaves like comapareTo()==0 means equals, not merely same size.

为避免这种情况,如果大小相同,则可以第二次比较其他对象,但是

To avoid this, comparison can secondarily look at something else if size is the same, but then it cannot be used to detect same sized different objects.

示例:

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}

您知道为什么会这样吗?

Do you have idea why it is so?

推荐答案

java.util.SortedSet javadoc:


请注意,排序集由排序集维护(无论是否如果已排序的集合
是要正确实现Set接口的对象,则必须提供等于显式比较器的
)。 (请参见
Comparable接口或Comparator接口以获取与equals一致的精确定义
。)之所以这样,是因为Set接口是根据equals操作定义的
,但是是一个有序集合执行
使用其compareTo(或compare)方法进行的所有元素比较,因此,从
的角度来看,此方法认为相等的
两个元素相等。排序集的行为是
的定义明确,即使其排序与equals不一致;

Note that the ordering maintained by a sorted set (whether or not an explicit comparator is provided) must be consistent with equals if the sorted set is to correctly implement the Set interface. (See the Comparable interface or Comparator interface for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a sorted set performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the sorted set, equal. The behavior of a sorted set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.

因此,换句话说, SortedSet 中断(或扩展) Object.equals() Comparable.compareTo 。请参见 compareTo 的合同:

Hence, in other words, SortedSet breaks (or "extends") the general contracts for Object.equals() and Comparable.compareTo. See the contract for compareTo:


强烈建议使用,但并非严格要求
(x.compareTo(y)== 0)==(x.equals(y))。一般来说,任何实现Comparable接口并违反此条件
的类
都应明确指出这一事实。推荐的语言是注意:此类的
具有与等式不一致的自然顺序。

It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is "Note: this class has a natural ordering that is inconsistent with equals."

这篇关于如果compareTo()返回0,为什么暗示对象相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆