假设我创建了一个名为Employee
的对象,它具有id,firstName,lastName和电子邮件,用于实例变量和相应的setter / getter方法。如果hashCode()
对象存储在集合对象中时不覆盖hashCode()
,那么如何计算Employee
?
答案 0 :(得分:23)
如果不覆盖hashcode(),则集合将使用Object类中的默认实现。此实现为不同的对象提供不同的值,即使它们根据equals()方法相等。
某些集合(如HashSet,HashMap或HashTable)使用哈希代码存储其数据并检索它。如果您没有以一致的方式实现hashcode()和equals(),那么它们将无法正常运行。
根据Javadoc:Object.hashcode()通常是通过将对象的内部地址转换为整数来实现的,但Java(TM)编程语言不需要这种实现技术。 。因此,我建议不要依赖具体的实施。对于实现的实际操作,请参阅this answer类似的问题。
答案 1 :(得分:8)
来自文档:
尽可能合理实用,由hashCode方法定义 class Object确实为不同的对象返回不同的整数。 (这个 通常通过转换内部地址来实现 将对象转换为整数,但这种实现技术不是 JavaTM编程语言所要求的。)
所以基本上当你存储在Map / Set / somethingThatRequiresHashCode中时,JVM将使用该实例的内部内存地址来计算hashCode,保证(尽管散列函数保证任何东西 - 它们不保证)每个不同实例将具有唯一的hashCode。
由于关于equals和hashCode的Object契约,这一点特别重要,因为:
类Object的equals方法实现最具辨别力 对象可能的等价关系;也就是说,对于任何非null 引用值x和y,当且仅当x时,此方法返回true 和y引用相同的对象(x == y的值为true)。
如果不覆盖equals,它将比较两个引用的内部地址,它与hashCode背后的逻辑相匹配。
如果您的问题与以下内容更相关:JVM是否会查看实例中的值以确定相等/计算哈希码,答案是否定的,如果您这样做:
MyObject a = new MyObject("a", 123,"something");
MyObject b = new MyObject("a", 123,"something");
a
和b
将使用不同的哈希码。
答案 2 :(得分:2)
来自有效的Java第二版
第9项:覆盖equals
时始终覆盖hashCode一个常见的 错误的来源是无法覆盖hashCode方法。您 必须覆盖覆盖等于的每个类中的hashCode。失败 这样做会导致违反一般合同 Object.hashCode,它将阻止您的类运行 正确地与所有基于散列的集合一起使用,包括 HashMap,HashSet和Hashtable。
我建议你阅读那一章。有很多例子,你可以学习,如果你不这样做会发生什么。
答案 3 :(得分:1)
它取决于集合,即使没有覆盖元素的hashCode,大多数集合也应该工作,除了HashSet
之类的集合,它依赖于元素hashCode才能正常工作。
请注意,集合的hashCode通常依赖于元素的hashCode:
返回此集合的哈希码值。而收藏 界面没有对一般合同的规定 Object.hashCode方法,程序员应注意任何类 覆盖Object.equals方法也必须覆盖 Object.hashCode方法以满足一般合同 Object.hashCode方法。特别是,c1.equals(c2)意味着 c1.hashCode()== c2.hashCode()
请参阅:http://docs.oracle.com/javase/6/docs/api/java/util/Collection.html#hashCode%28%29
答案 4 :(得分:0)
**type of field** **hash code formula**
boolean fieldHash = f ? 0 : 1
any integer type except long fieldHash = (int) f
long fieldHash = (int) (f ^ (f >>> 32))
float fieldHash = Float.floatToIntBits( f )
double int v=Double.doubleToLongBits(f)
fieldHash (int) (v ^ (v >>> 32))
any Object reference fieldHash = f.hashCode()
如果您编写自定义类型,则负责创建一个最佳表示当前实例状态的良好hashCode
实现。