Java中哈希码和等式方法之间的关系
2022-08-31 09:17:22
我在很多地方读到过,虽然Java中覆盖了方法,但也应该覆盖方法,否则就是“违反契约”。equals
hashCode
但到目前为止,如果我只覆盖等于方法,而不是哈希代码方法,我还没有遇到任何问题。
合同是什么?为什么我在违反合同时没有遇到任何问题?在哪种情况下,如果我没有覆盖hashCode方法,我会遇到问题吗?
我在很多地方读到过,虽然Java中覆盖了方法,但也应该覆盖方法,否则就是“违反契约”。equals
hashCode
但到目前为止,如果我只覆盖等于方法,而不是哈希代码方法,我还没有遇到任何问题。
合同是什么?为什么我在违反合同时没有遇到任何问题?在哪种情况下,如果我没有覆盖hashCode方法,我会遇到问题吗?
您将遇到的问题是集合,其中元素的单一性是根据 和 计算的,例如 ..equals()
.hashCode()
HashMap
顾名思义,它依赖于哈希表,而哈希桶是对象的 函数。.hashCode()
如果你有两个对象,但它们有不同的哈希代码,你就输了!.equals()
这里合约中重要的部分是:.equals()
的对象必须具有相同的.hashCode()
。
这一切都记录在javadoc for Object
中。Joshua Bloch说你必须在 Effective Java 中做到这一点。说得够多了。
根据该文档,hashCode的默认实现将返回一些因每个对象而异的整数
尽管合理实用,但由类 Object 定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常是通过将对象的内部地址转换为整数来实现的,但 JavaTM 编程语言不需要这种实现
技术。
但是,有时您希望具有相同含义的不同对象的哈希代码相同。例如
Student s1 = new Student("John", 18);
Student s2 = new Student("John", 18);
s1.hashCode() != s2.hashCode(); // With the default implementation of hashCode
如果在集合框架中使用哈希数据结构(如 HashTable、HashSet),则会出现此类问题。特别是对于像HashSet这样的集合,你最终会有重复的元素并违反Set合约。