Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hashcode和equals方法契约_Java_Equals_Hashcode - Fatal编程技术网

Java Hashcode和equals方法契约

Java Hashcode和equals方法契约,java,equals,hashcode,Java,Equals,Hashcode,我知道,当我们重写equals()方法时,我们也需要重写hashcode()方法 但我不明白为什么我们必须这样做 在Joshua Bloch的书中明确指出,我们必须这样做,因为当我们处理基于哈希的集合时,满足哈希代码契约是至关重要的,我承认这一点,但如果我没有处理基于哈希的集合呢 为什么仍然需要它?因为这就是它的本意: 每当a.equals(b)时,a.hashCode()必须与b.hashCode()相同 在某些用例中,您不需要hashcode(),大多数情况下都是自编场景,但您永远无法确定

我知道,当我们重写
equals()
方法时,我们也需要重写
hashcode()
方法

但我不明白为什么我们必须这样做

在Joshua Bloch的书中明确指出,我们必须这样做,因为当我们处理基于哈希的集合时,满足哈希代码契约是至关重要的,我承认这一点,但如果我没有处理基于哈希的集合呢


为什么仍然需要它?

因为这就是它的本意:

每当a.equals(b)时,a.hashCode()必须与b.hashCode()相同


在某些用例中,您不需要
hashcode()
,大多数情况下都是自编场景,但您永远无法确定,因为如果使用
equals()

数据结构,例如
HashMap
,则实现可以而且可能也依赖于
hashcode()
,这取决于契约

HashMap通过使用hashcode对条目进行bucketize来实现神奇的性能属性。放置在映射中具有相同
hashcode()
值的每个项目都将放置在同一个bucket中。这些“冲突”是通过使用
equals()
在同一个bucket内进行比较来解决的。换句话说,hashcode用于确定映射中可能相等的项的子集,并以这种方式快速消除绝大多数项的进一步考虑

这仅在相等的对象放在同一个bucket中时有效,只有当它们具有相同的hashcode时才能确保这一点

注意:在实践中,冲突的数量比上面可能暗示的要高得多,因为使用的bucket数量必然比可能的hashcode值的数量小得多。

为什么要覆盖Equals? 使用
equals
方法希望找出它们在逻辑上是否等价,而不是 它们是否引用同一对象

现在来看HashCode 哈希函数被调用以生成哈希代码每次都应返回相同的
哈希代码,
当函数应用于相同或相等的对象时。换句话说,两个
相等的对象必须一致地生成相同的哈希代码

对象类
提供的HashCode的实现不是基于
逻辑等价性

因此,现在如果您不重写
hashCode
而是重写
equals
,那么根据您的说法,两个对象是相等的,因为它们将通过
equals()
测试,但根据Java,它们不是

后果:
  • 设置
    开始允许重复
  • Map#get(key)
    将不会返回正确的值
  • 等等许多其他的后果

  • 根据约书亚·布洛赫的书

    错误的一个常见来源是未能覆盖哈希代码 方法必须在每个重写的类中重写哈希代码 等于。不这样做将导致违反一般规则 Object.hashCode的契约,这将阻止您的类 与所有基于哈希的集合一起正常运行, 包括HashMap、HashSet和Hashtable

    重写equals时未能重写hashcode违反了Object.hashcode的约定。但如果您仅在非基于散列的集合上使用对象,则这不会产生影响


    但是,如何预防;其他开发人员正在这样做。另外,如果一个对象符合集合元素的条件,那么最好为所有集合提供支持,不要在项目中包含未完成的对象。这将在将来的任何时候失败,并且您将因为在实现时没有遵循联系人而被抓获:)

    这个问题在SO中被回答了很多次,但我仍将尝试回答这个问题

    为了完全理解这一概念,我们需要理解hashcode和equals的目的、它们是如何实现的,以及这个契约到底是什么(当equals被重写时hashcode也应该被重写)

    equals方法用于确定对象的相等性。对于基元类型,很容易确定相等性。我们可以很容易地说int 1总是等于1。但是这个相等的方法谈论的是对象的相等。对象相等性取决于实例变量或任何其他参数(完全取决于实现-您希望如何比较)

    如果我们想要一些定制的比较,我们需要重写这个相等的方法,假设我们想要说两本书是相同的,如果它们有相同的标题和作者,或者我可以说两本书是相等的,如果它们有相同的ISBN

    hashcode方法返回对象的哈希代码值。对象哈希代码的默认实现为不同的对象返回不同的整数。该整数是根据对象的内存地址计算的

    因此,我们可以说equals方法的默认实现只是使用hashcode检查对象的相等性。但是对于书的例子,我们需要不同的方法

    同样,只要相等,相等的对象必须产生相同的哈希代码,但是不相等的对象不需要产生不同的哈希代码


    如果不使用基于哈希的集合,您可以打破契约,不需要重写hashcode方法-因为您不会在任何地方使用默认实现,但我仍然不建议您这样做,并且会说,当您将来将这些东西放入集合时,您可能需要它,因为任何两个
    相等的对象都必须,通过