了解什么是hashcode?
hashCode 是一个在 Java 等编程语言中常见的方法,用于为对象生成一个整数表示,通常称为哈希码或哈希值。这个哈希码主要用于哈希表数据结构,可以快速地定位对象在哈希表中的位置。
以下是关于 hashCode 的一些也行特性:
- 唯一性:理想情况下,每个对象的 hashCode 应该是唯一的,但在实际应用中,由于整数范围有限,哈希冲突(即不同的对象产生相同的 hashCode)是可能的。好的哈希算法会尽量减少这种冲突。
- 一致性:对于同一个对象,只要其内部状态没有发生变化,多次调用 hashCode 方法应该返回相同的结果。
- 效率:计算 hashCode 的过程应该尽量快,避免进行复杂的计算。
- 与 equals 方法的关系:在 Java 中,如果两个对象通过 equals() 方法被认为是相等的,那么它们的 hashCode 必须相同。但反过来不一定成立,即哈希码相同并不意味着两个对象是相等的。
- 自定义对象的 hashCode:当你重写 equals 方法时,通常也需要重写 hashCode 方法,以确保它们之间的契约不被破坏。
- 哈希表应用:哈希表(如 Java 中的 HashMap 和 HashSet)使用 hashCode 方法来快速定位元素。当插入、查找或删除元素时,哈希表会首先使用 hashCode 来缩小搜索范围,从而提高操作效率。
在 Java 中,每个对象都继承自 Object 类,而 Object 类定义了一个默认的 hashCode 方法。但是,当你重写 equals 方法时,通常建议也重写 hashCode 方法,以确保两个方法之间的契约关系得到维护。
为什么重写equals方法时还要重写hashCode方法?
因为需要保持equals()和hashCode()之间的约定一致,以确保类在哈希表(如HashMap、HashSet等)中的正确行为。这两个方法之间的关系遵循以下原则:
- Reflexive(自反性):a.equals(a)应为true,这意味着a.hashCode()应该也是同样的结果。
- Symmetric(对称性):如果a.equals(b)为true,则b.equals(a)也应该为true,相应地,a.hashCode()和b.hashCode()应该相等。
- Transitive(传递性):如果a.equals(b)为true且b.equals(c)为true,则a.equals(c)也应为true,相应的,a.hashCode()、b.hashCode()和c.hashCode()应该相等或至少根据哈希算法逻辑上相等。
- Consistent(一致性):多次调用同一个对象的equals()方法,结果应该保持一致,同样,多次调用hashCode()也应该返回相同的值,前提是对象的状态没有改变。
- For any non-null reference value x, x.equals(null)should returnfalse`.(非空对象与null比较)
当您重写equals()方法来定义对象间的相等性时(即根据业务逻辑判断两个对象是否“相等”),如果没有同时重写hashCode()方法,可能会导致违反上述原则,尤其是在使用哈希表的集合类中出现问题。具体来说,可能会出现以下问题:
- 违反了对称性:如果两个对象根据equals()认为是相等的,但它们的hashCode()返回不同的值,这将导致在像HashSet或HashMap这样的集合中,可能一个对象能被找到而另一个不能,即使你认为它们是等价的。
- 效率降低:在哈希表中查找元素时,首先会使用hashCode()来确定元素的桶位置,如果equals()相等的对象散列到不同的桶中,那么在这些集合中的添加、删除、查找操作的效率会大大降低。
总之,每次重写 equals 方法时都必须重写 hashCode 方法,否则程序将无法正常运行。你的 hashCode 方 法必须遵从 Object 类指定的常规约定,并且必须执行合理的工作,将不相等的哈希码分配给不相等的实例。