在Java中,hashCode和equals是两个非常重要的方法,它们通常一起使用来判断对象的相等性。
hashCode方法用于生成对象的哈希码,主要作用是在哈希表中快速查找和比较对象。
而equals方法用于比较两个对象是否相等,在集合类,比如:HashSet、HashMap…等中,这两个方法比较重要。
equals作用
equals
方法:用于比较两个对象是否相等,默认情况下,Object
类中的 equals
方法比较的是对象的引用。
实现如下:
public boolean equals(Object obj) { return (this == obj); }
直接调用==,即比较对象是否指向“同一个内存地址”。
也就是说,只有当两个引用指向同一个对象时,equals
方法才返回 true
。
但是,如下String,得到的却是“true”。
public static void main(String[] args) { String str1 = new String("mikechen"); String str2 = new String("mikechen"); System.out.println(str1.equals(str2)); }
返回的是:
true
原因是,String重写了“equals”方法,如下所示:
public boolean equals(Object anObject) { if (this == anObject) { // 先判断引用是否相同; return true; } if (anObject instanceof String) {// 再判断类型是否一致; // 最后判断内容是否一致; String anotherString = (String)anObject;; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
使用equals方法,内部实现分为三个步骤:
- 首先,比较引用是否相同,是否为同一对象;
- 其次,再判断类型是否一致,是否为同一类型;
- 最后,比较内容是否一致。
Java 中所有内置的类的 equals 方法的实现步骤均是如此,比如: Integer,Double …等包装器类。
重写equals
方法时需要遵循以下约定:
- 自反性:对于任何非空引用值
x
,x.equals(x)
应该返回true
。 - 对称性:对于任何非空引用值
x
和y
,如果x.equals(y)
返回true
,则y.equals(x)
也应该返回true
。 - 传递性:对于任何非空引用值
x
、y
和z
,如果x.equals(y)
返回true
,并且y.equals(z)
返回true
,则x.equals(z)
也应该返回true
。 - 一致性:对于任何非空引用值
x
和y
,在对象没有被修改的情况下,x.equals(y)
在多次调用时应该始终返回相同的结果。
hashCode作用
hashCode
方法在 Java 中用于为对象生成一个整数散列码,主要作用是在哈希表中快速查找和比较对象。
public native int hashCode();
hashCode的作用,体现在2个方面:
1. 快速查找
hashCode
方法将对象映射为一个整数值,这个整数值用于确定对象在哈希表中的存储位置。
通过使用哈希码,可以快速找到对象所在的桶(bucket),从而提高查找效率。
2. 匹配对象
在哈希表中,hashCode
和 equals
方法共同作用来确保对象的唯一性和正确查找。
哈希表首先使用 hashCode
确定对象可能所在的桶,然后再使用 equals
方法来逐个比较桶中的对象,确保找到正确的对象。
如果当我们向哈希表中添加对象object时,该桶位置没有对象,可以直接将对象插入该位置。
如果该位置有对象(可能有多个,通过链表实现),则调用equals()方法比较这些对象与object是否相等。
如果相等,则不需要保存object,如果不相等,则将该对象加入到链表中。
这也就解释了为什么equals()相等,则hashCode()必须相等。
equals和hashCode的关系
- 一致性:如果两个对象根据
equals
方法比较是相等的,那么它们的hashCode
必须相同。反之,不一定相同,因为不同的对象可能具有相同的哈希码(哈希冲突)。 - 必要性:如果只重写
equals
方法而不重写hashCode
方法,可能会导致在使用哈希表(如HashMap
或HashSet
)时无法正确找到对象。 - 建议:重写
equals
方法时总是要重写hashCode
方法,以确保两个相等的对象在集合框架中具有相同的哈希码。