5

可能重复:
什么是对象哈希码

假设我创建了一个名为的对象,Employee它具有实例变量的 id、firstName、lastName 和 email 以及相应的 setter/getter 方法。如果将对象存储在集合对象中时不覆盖对象,如何hashCode()计算?hashCode()Employee

4

5 回答 5

28

如果你不覆盖 hashcode() ,那么 Object 类中的默认实现将被集合使用。此实现为不同的对象提供不同的值,即使根据 equals() 方法它们相等。

一些集合,如 HashSet、HashMap 或 HashTable 使用哈希码来存储和检索数据。如果您没有以一致的方式实现 hashcode() 和 equals(),那么它们将无法正常运行。

编辑:

根据Javadoc:Object.hashcode()“通常通过将对象的内部地址转换为整数来实现,但 Java(TM) 编程语言不需要这种实现技术”。因此,我建议不要依赖特定的实现。有关实现的真正作用,请参阅对类似问题的回答

于 2013-01-30T16:22:40.930 回答
9

从文档中:

在合理可行的情况下,由 Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常通过将对象的内部地址转换为整数来实现,但 JavaTM 编程语言不需要这种实现技术。)

所以基本上当你存储在 Map/Set/somethingThatRequiresHashCode 中时,JVM 将使用该实例的内部内存地址来计算 hashCode,保证(就像散列函数保证任何东西一样——它们不保证)每个不同的实例都会有一个唯一的哈希码。

这一点尤其重要,因为 Object 契约涉及 equals 和 hashCode,因为:

Object 类的 equals 方法实现了对象上最有区别的可能等价关系;也就是说,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象(x == y 的值为 true)时,此方法才返回 true。

如果不覆盖equals,它将比较两个引用的内部地址,这与hashCode背后的逻辑相匹配。

如果您的问题与以下内容更相关:JVM 是否会查看实例中的值以确定相等/计算哈希码,如果您这样做,答案是否定的:

MyObject a = new MyObject("a", 123,"something");
MyObject b = new MyObject("a", 123,"something");

a并且b会有不同的哈希码。

于 2013-01-30T16:21:14.880 回答
2

来自有效的 Java 第 2 版

第 9 条:当你覆盖 equals 时,总是覆盖 hashCode

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

我建议你读那一章。有很多例子,你可以学习,如果你不这样做会发生什么。

于 2013-01-30T16:24:47.070 回答
1

这取决于集合,即使元素的 hashCode 未被覆盖,大多数集合也应该工作,除了 HashSet依赖元素 hashCode 才能正常工作的集合。请注意,集合的 hashCode 通常依赖于元素的 hashCode:

返回此集合的哈希码值。虽然 Collection 接口没有对 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

于 2013-01-30T16:41:52.733 回答
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能够最好地代表当前实例状态的良好实现。

http://content.hccfl.edu/polllock/AJava/HashCode.htm

于 2013-01-30T16:28:27.433 回答