当前位置: 首页 > 面试题库 >

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

胡劲
2023-03-14
问题内容

让我们上一堂课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接口且违反此条件的类都应明确指出这一事实。推荐的语言是“注意:此类具有与等式不一致的自然顺序”。



 类似资料:
  • 我知道(-0==0)是真的。我很想知道为什么-0 当我在stackoverflow执行上下文中运行这段代码时,它返回。 但是当我在浏览器控制台中运行相同的代码时,它返回。那是为什么呢?我试图在谷歌上搜索它,但没有找到任何有用的东西。这个问题可能不会给某个人的实际例子增加价值,我想了解JS是如何计算它的。

  • 问题内容: 我有这样的事情: 而且我总是得到“时钟周期为:0-0”的输出 知道为什么会这样吗? (仅给出一点点细节,something_else()函数使用蒙哥马利表示法执行从左到右的求幂运算,而且我不确定不确定something_else()函数确实花费了一些不可忽略的时间。) 这是在Linux上。uname -a的结果是: 问题答案: 该功能不测量CPU时钟周期。 C说: “ 从实现定义的仅与

  • 问题内容: 为什么以下返回0? 问题答案: 月份从0(一月)到11(十二月)进行编号。 参考:

  • 问题内容: 什么回报? 答案会一样吗? Linux GCC的输出: 输出每次都会保持变化。这是标准答案吗?为什么除了学术研究之外,还有谁会对获得这样的指示感兴趣? 编辑: 如果返回伪指针,则以下内容如何工作: 编辑: 以下代码为每次迭代输出“可能”。为什么不失败? 问题答案: 其他人已经回答了如何工作。我将回答您提出的尚未回答的问题之一(我认为)。问题是关于: 什么回报?答案会一样吗? 该标准规定

  • 问题内容: 我有以下代码。应该返回表的最后一行的mysqli_insert_id()(在本例中为“ $ last_row”)始终返回0。为什么会这样呢? 问题答案: 并 没有 返回表的最后一排的ID。从文档中,它: …返回由查询产生的ID,该查询是对具有具有AUTO_INCREMENT属性的列的表进行的。如果最后一个查询不是or 语句,或者如果修改后的表没有带有属性的列,则此函数 将返回零 。 (

  • 问题内容: 我在jsfiddle.net上玩,我很好奇为什么返回true? 这样: 但这不是: 这个怪癖有用吗? 问题答案: 操作顺序导致在javascript中解释为产生,并且true计为1,导致其返回true。 这也是为什么返回false,返回true,为什么将其解释为,从而导致的原因。