Java.lang.Object 有两个重要的放到
hashcode和equals
其中Object类是Java类集成机制的基础,是所有对象、数组、集合的公共基类。
在Object类中,equals方法的定义:
public boolean equals(Object obj){
return this == obj;
}
即是对象引用地址的比较。
而通常我们常用的String、包装类、以及自定义的实体都会重写该方法。实现对象本身是否相等的判断。
以下是String类型的实现代码。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n– != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
而hashcode方法会给传入的对象返回一个hashcode值,同一个对象调用hashcode方法,必然返回相等的值,
两个对象的 A.equals(B) 则要求 A、B对象的hashcode方法的返回值要相等
例子:HashSet 、HashMap
我们知道set类型的集合,要求内部对象唯一,不可重复,而要保证不可重复,就需要使用Object.equals方法比较,但是这会有一个效率问题,即 集合内对象数量增大时(n个),每次加入一个对象,都要进行n次比较;为提升效率,Java引用哈希表,
哈希表实际是一种对象算法,也称为散列算法,通过将对象计算后得到的值,对应到hash表中,这样在set集合新增对象时,只需要计算对象哈希值hashcode方法后,定位到哈希表中对应位置是否有对象,没有就直接加入,有的话就调用equals方法,相等则舍弃该对象,不相等则,散列到其他位置。一般情况下,很少需要调用equals方法,通过这个过程可以大大提升效率。当然了这带来了一个哈希冲突解决的问题;同样,对象数量是无穷的,而hash表的大小是有限的。
统一上述方法,可以得出另一个结论:A、B对象的hashcode值相等,A.equals(B)不一定成立
两个对象,equals相等,hashcode不一致,调用hashset添加对象时,就有可能两个对象都添加进去,而这与Set的定义不符。
同样在HashMap中,如两个对象的equals不一致,而hashcode相等,添加时,两个对象就会哈希冲突,两个对象会放在同一个数组索引下的链表内,该情况会产生大量冲突。
如重写equals而不重写hashcode,则 根据equals,两个不同的实例有可能在逻辑上是相等的,根据原生的Object.hashcode,是两个对象,违反了:相等的对象必须有相等的散列。
所以Java要求在重写equals时hashcode方法要一起重写。equals不相等的对象,hashcode也是可能相等的(哈希冲突,再散列)
Java代码中判断对象是否相等,一般通过两步
1.判断对象的hashcode(哈希表),若不相等则对象不相等,如相等则进行第二步
2.判断equals 若相等则对象相等,不相等则不是一个对象
分为两步大大提升了效率。