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

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

问题描述

让我们有一个。 Person有一个名字和高度。

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

Equals和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:


请注意由排序集维护的排序(无论是否
提供了显式比较器)如果
,则必须与equals一致才能正确实现Set接口。 (请参阅
Comparable接口或Comparator接口以获得与equals一致的精确定义
。)这是因为Set接口是根据equals操作定义的
,但是是有序集合使用compareTo(或compare)方法执行
所有元素比较,因此
这个方法认为相等的两个元素,从排序集的
角度来看,是相等的。即使排序与equals不一致,有序集的行为也是明确定义的
;它只是
无法遵守Set接口的一般合约。

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接口并违反此条件
的任何类
都应清楚地表明这一事实。推荐的语言是注意:
这个类的自然顺序与equals不一致。

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."

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

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