Java基础之hashCode()和equals()

40 阅读2分钟

问题:两个对象的 hashCode() 相同,则 equals() 也一定为 true 吗?

不一定。

比较项是否一定
equals() == true → hashCode() == true✅ 是的(必须)
hashCode() == true → equals() == true❌ 不一定(可能是哈希碰撞)

hashCode() 是一个 哈希函数,它的目标是尽可能快地分组对象。

Java 的设计规范是:equal 的对象必须有相同的 hashCode,但相同 hashCode 的对象不一定 equal。

String a = "FB";
String b = "Ea";
System.out.println(a.hashCode()); // 2236
System.out.println(b.hashCode()); // 2236
System.out.println(a.equals(b)); // false

hashCode() 返回的是 int 类型,只有 2³² 个可能的值,但对象可以有无穷多种,所以总会有哈希碰撞的可能。


引申问题1:hashCode() 和 equals() 的关系

Java 规范有一个 非常重要的约定

  1. 如果两个对象 equals() 返回 true,那么它们的 hashCode() 必须 相等。
  2. 如果两个对象 equals() 返回 false,它们的 hashCode() 可以相等(哈希冲突),但为了性能最好尽量减少冲突。

所以,hashCode() 和 equals() 必须一起正确重写!特别是你要把对象放进 HashMap、HashSet、Hashtable 这类基于哈希的集合中。

因为 HashMap、HashSet 的工作机制如下:

  1. 先通过 hashCode() 快速定位桶(bucket)。
  2. 再通过 equals() 精确比较对象是否相等。

所以必须做到:保证 equals() 相等时,hashCode() 也一致(否则找不到桶,取不到值)。否则 HashMap 和 HashSet 会出现数据丢失、查找失败、重复数据等问题!

如果你 重写 equals(),一定要配套重写 hashCode() ,并保证两个相等的对象 hashCode 一样。重写一个,就要重写另一个,否则你在用 HashMap / HashSet 时会踩坑只重写equals不重写hashCode,HashSet中仍然有重复元素,因为虽然p1 和 p2的内容相等,但是它们的hashCode()不等;所以,HashSet在添加p1和p2的时候,认为它们不相等。


引申问题2:hashCode()作用

hashCode() 是对象的散列值,主要用于哈希存储结构中(如 HashMap、HashSet、HashTable),用来快速定位对象在哈希结构 中所在的“桶(bucket)”。

如果没有hashCode(),也能完成对象是否相等的对比,但是效率极低,在put和get的时候,需要遍历所有数据进行对比,


引申问题3:我们可以将自定义对象作为HashMap的key吗?如果可以,需要额外做什么吗?

可以!但是要正确地实现 hashCode() 和 equals() 方法。否则会出现“看似相等却查不到”的问题。