Java 如果类没有用作hashmap中的键,那么重写hashcode有什么实际意义吗?

Java 如果类没有用作hashmap中的键,那么重写hashcode有什么实际意义吗?,java,hashmap,key,hashcode,Java,Hashmap,Key,Hashcode,我最近学习了hashCode函数和HashMaps,并尝试为自己的类创建自己的hashCode函数。从我所做的研究来看,从实用的角度来看,需要重写hashCode的唯一原因似乎是该类将用作HashMap中的键,或者hashCode函数在其他地方使用。我知道它是equals和hashCode契约的一部分要重写,将来其他用户可能想在HashMap中使用它,但为了理解起见,我想知道该类是否从未用作键,我还需要重写hashCode函数吗?否。但是请记住,HashMap中的键与HashSet中的值相同,因

我最近学习了hashCode函数和HashMaps,并尝试为自己的类创建自己的hashCode函数。从我所做的研究来看,从实用的角度来看,需要重写hashCode的唯一原因似乎是该类将用作HashMap中的键,或者hashCode函数在其他地方使用。我知道它是equals和hashCode契约的一部分要重写,将来其他用户可能想在HashMap中使用它,但为了理解起见,我想知道该类是否从未用作键,我还需要重写hashCode函数吗?

否。但是请记住,
HashMap
中的键与
HashSet
中的值相同,因此您也无法将该对象存储在
HashSet
中(至少如果您打算将其用于内容平等).

我认为如果您没有在密钥中使用对象或任何其他基于哈希的数据结构,那么您是正确的,您不需要覆盖object.JVM的hashcode方法。提供hashcode的默认实现

始终会有默认的
hashCode
实现,它在内部使用标识哈希代码。也就是说,该类可以在
HashSet
中使用,甚至可以作为
HashMap
中的键使用,但这将不是非常有效或有意义的-如果不实现
equals
,则使用
是没有意义的

一个重要的考虑事项是:<代码>等于和 HASCODE < /代码>之间的合同。也就是说,如果覆盖

equals
,则必须覆盖
hashCode
,使其为两个wrt相等的实例返回相同的值。
的实现等于
。换句话说,以下规则必须始终适用:


如果
a.equals(b)==true
,那么
a.hashCode()==b.hashCode()
无论何时实现
equals
,您都应该始终实现
hashCode
,因为即使您从未将对象放在HashMap中,您也不知道您正在使用的库会做什么。库可以自由地依赖对象的
hashCode
,而无需告诉您

即使您只是让IDE自动生成
hashCode
以及
equals
,或者即使它只是

public int hashCode() {
    raise RuntimeException("This type doesn't support hashCode (for now).");
}

您不应该让您的
hashCode
与您的
equals
不一致。是的,如果您重写
equals
,您也应该始终重写
hashCode
,即使您不希望对象存储在
HashMap
HashSet
中。有几个原因

  • 您的对象今天可能不会存储在
    HashMap
    HashSet
    中,但六个月后,您可能会决定这样做,事情似乎会正常工作,直到它们严重损坏。这时,您会对自己说“%$^^&%*&我应该实现
    hashCode
    !”

  • 您的对象可能被其他人使用,他们希望您实现
    hashCode
    。当他们将对象存储在
    HashMap
    中,但它不起作用时,他们会说“%$^^&%*&Aaron应该实现
    hashCode
    !”

  • 您可能会将对象交给某个库,而您不知道该库可能希望将对象存储在基于哈希的集合中

  • 如果您的对象曾经存储在容器对象中,即使该容器本身不是基于哈希的,容器的
    hashCode
    通常在逻辑上依赖于您的对象的
    hashCode
    。例如,请参阅或

  • hashCode
    有时用于使相等性检查短路


  • 归根结底,
    hashCode
    /
    等于
    契约的要点是每个人都依赖于契约的正确实施。关于遵守合同的假设贯穿于整个大型系统,而不仅仅是在基于散列的集合中。

    事实并非如此。看看我的答案。或者你也许应该详细说明你所说的“内容平等”是什么意思。如果您只需要引用相等,那么这不是问题,但是如果您想要内容相等,那么它就是问题。如果对您来说是一个新术语,请查找内容平等与引用平等。鉴于OP对Java来说似乎是非常新的,我认为答案应该更精确。他似乎理解equals/hashCode契约。你只是在重复他在你的回答中已经知道的事情。另一方面,我给了他一个问题的答案,即“否”。这个术语通常不是“值相等”吗?在基于散列的集合之外是真的吗?@shmosel我想我以前见过(在基于散列的集合之外)这样做,但我可能已经做了很多挖掘来找到一个例子。但根据equals/hashCode合同,这是合法的,所以我认为很可能有人在某处做了这件事。@shmosel啊,没花多长时间。看看这个方法。我不太了解这段代码的功能,但它看起来是正确的。它缓存hashCode值,并避免在hashCodes不相等时进行昂贵的相等检查。这是一个检查自己的hash代码的类,因此它不会直接与OP的情况并行,其中
    equals()
    显然不依赖
    hashCode()
    。我知道,可以在外部进行类似的短路;我只是想知道它是否发生在现实世界中。@AaronBarnard哈希代码的主要用途是1)基于哈希的集合;2) 不一定是基于散列的容器,但在计算自己的散列码时使用它;以及3)同等和类似情况下的短路。与fir相比,最后一种情况相当少见