首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >重写等于()时重写hashCode()

重写等于()时重写hashCode()
EN

Stack Overflow用户
提问于 2012-12-10 16:03:09
回答 5查看 361关注 0票数 3

可能重复: 在Java中,为什么等于()和hashCode()必须保持一致?

我读到,当重写equals()时,应该始终有when ()。

有人能给出一个实际的例子,说明为什么它可能是错误的,否则呢?即当覆盖等于()而不是hashCode()时可能出现的问题。

当我们重写等于()时,是否需要编写一个健壮的hasCode()函数?还是一个简单的实现就足够了?

例如,

下面这种糟糕的实现足以满足equals() & hashCode()之间的约定?

代码语言:javascript
运行
复制
public int hashCode() {
   return 91;
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-12-10 16:06:11

equals()hashCode()是在某些集合(如HashSetHashMap )中联合使用的,因此您必须确保如果使用这些集合,则必须根据约定覆盖hashCode

如果您根本不覆盖hashCode,那么HashSetHashMap就会有问题。特别是,两个“相等”的对象可以放在不同的散列桶中,尽管它们应该是相等的。

如果您确实覆盖了hashCode,但是操作很差,那么您就会出现性能问题。HashSetHashMap的所有条目都将放在同一个桶中,您将失去O(1)的性能,取而代之的是O(n)。这是因为数据结构本质上变成了一个线性检查的链表。

至于破坏这些条件之外的程序,这是不可能的,但您永远不知道API (特别是第三方库中的API)何时将依赖于这个契约。对于没有实现任何一个对象的对象,契约都是被维护的,因此可以想象库可能在某个地方依赖于此而不使用散列桶。

在任何情况下,实现一个好的hashCode都很容易,特别是在使用IDE的情况下。Eclipse和Netbeans都具有为您生成equalshashCode的能力,可以遵循所有契约,包括equals的逆规则(断言a.equals(b) == b.equals(a))。您所需要做的就是选择要包含的字段。

票数 2
EN

Stack Overflow用户

发布于 2012-12-10 16:07:40

equalshashcode都是基于对象的单一性原则。如果equals返回true,则两个对象的哈希代码必须相同,否则基于哈希的结构和算法可能会有未定义的结果。

考虑基于哈希的结构,如HashMap。将调用hashcode作为获取密钥引用的基础,而不是equals,这使得在大多数情况下不可能找到密钥。另外,hashcode的一个糟糕的实现会产生冲突(同一个hashcode的多个对象,哪一个是“正确的”对象?)这会影响性能。

IMHO,覆盖equalshashcode (而不是覆盖两者)应该被认为是一种代码气味,或者至少是潜在的bug源。也就是说,除非您100%肯定它迟早不会影响您的代码(我们什么时候这么确定?)。

注意:有各种库可以通过equalshashcode构建器来提供对此的支持,比如阿帕奇公域HashcodeBuilderEqualsBuilder

票数 4
EN

Stack Overflow用户

发布于 2012-12-10 16:29:36

下面的代码说明了您可以通过不实现hashCode()来引入一个bug : Set.contains()将首先检查对象的hashCode(),然后检查.equals()。因此,如果不同时实现这两种功能,.contains()就不会以直观的方式运行:

代码语言:javascript
运行
复制
public class ContainsProblem {

// define a class that implements equals, without implementing hashcode
class Car {
    private String name;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Car)) return false;
        Car car = (Car) o;
        if (name != null ? !name.equals(car.name) : car.name != null) return false;
        return true;
    }

    public String getName() {return name;}

    public Car(String name) { this.name = name;}
}

public static void main(String[] args) {
    ContainsProblem oc = new ContainsProblem();

    ContainsProblem.Car ford = oc.new Car("ford");
    ContainsProblem.Car chevy = oc.new Car("chevy");
    ContainsProblem.Car anotherFord = oc.new Car("ford");
    Set cars = Sets.newHashSet(ford,chevy);

    // if the set of cars contains a ford, a ford is equal to another ford, shouldn't
    // the set return the same thing for both fords? without hashCode(), it won't:
    if (cars.contains(ford) && ford.equals(anotherFord) && !cars.contains(anotherFord)) {
        System.out.println("oh noes, why don't we have a ford? isn't this a bug?");
    }
}
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13804547

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档