equals和hashcode
一. equals已经能实现对比的功能了,为什么还要hashCode呢?
因为重写的equals里一般比较的比较全面且复杂,效率较低,而利用hashCode进行对比,效率较高,而且哈希算法需要hashcode
二.hashCode既然效率这么高为什么还要equals呢?
因为hashCode不完全可靠,有时候equals不成立的对象会生成相同的hashcode,我们可以总结得出:
1.equals成立 ---> hashCode肯定相等
也就是用equals对比是绝对可靠的
2.hashCode相等 ---> equals不一定成立
也就是hashCode不是绝对可靠
2.1 equals不等而hashcode相等的例子
public class Student {
private String name;
private Integer age;
@Override
public int hashCode {
return name.hashCode;
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
else if (!(obj instanceof Student))
return false;
else {
return this.name.equals(((Student) obj).name)
&& this.age.equals(((Student) obj).age);
}
}
}
//两个不同年龄姓名相同的人会有相同的hashcode值,但equals不成立
public class Teacher {
private String name;
private Integer age;
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
else if (!(obj instanceof Student))
return false;
else {
return this.name.equals(((Student) obj).name)
&& this.age.equals(((Student) obj).age);
}
}
}
//名字相同的老师和学生hashcode将会相同,但equals不成立
三.hashCode和equals的使用
对于需要大量的对比,如果都用equals去做效率太低,解决方法是
首先用hashCode去对比
如果hashCode不同,则这两个对象肯定不相等(也不必再用equals了)
如果hashCode相同使用equals
如果equals也成立,则表示这两个对象是真的相同,这样能在保证对比正确性的前提下大大提高效率
这个处理方法应用在HashSet,HashMap,HashTable等容器中
比如HashSet里要求对象不能重复,则他要对添加进去的每个对象进行对比,对比规则如上所说,先对比hashCode,如果相同,再用equals验证,如果hashCode都不同,则两对象肯定不同,省去了equals,提升了效率
四.什么时候需要重写hashcode和equals方法
一句话总结
一般的地方不需要重载hashCode,只有当类需要放在HashTable、HashMap、HashSet等hash结构容器内时才需要重载hashCode和equals
如果我们的自定义类对象需要放进hashSet,并发挥hashSet的特性(即不包含一样的对象),则我们就要重写我们类的hashCode和equals方法了.否则默认的继承自Object的hashcode和equals方法如下
很明显因为自定义类创建对象在堆内地址永远不可能相同,所以自定义类的equals除了他本身永远不可能成立
//Object.class
@HotSpotIntrinsicCandidate
public native int hashCode;
//返回对象地址,是一个本地方法(native method),由jvm底层实现
public boolean equals(Object obj) {
return this == obj;
}
//比较对象地址是否相同
五.为什么equals成立,hashCode就一定相等,而hashCode相等,equals却不一定成立?
1.为什么equals相等,hashCode就一定要相等
1.如果两个equals的对象,hashcode都不等,那么我们将永远无法找到这个值,整个哈希算法都会不成立所以equals成立,算法要求hashCode相等.
2.其次我们一般是使用类中部分属性值计算hashcode,而两个equals的类一般属性值都会相同,没有道理hashcode不相同.
2. 为什么hashCode相等,equals却不一定成立?
1.首先需要明确的是并不是不想让他们具有对称性,即equals相等,hashcode相等,反之亦然,而是函数的限制导致这种目标是不可能实现的,当你使用一个函数根据一段String生成hashcode值,你很难确定这个世界是不是存在一段String跟你原本的String完全不同,但会生成相同的hashcode值(当然概率极低).
2.其次我们一般是使用类中部分属性值计算hashcode,但比如Student和Teacher他们都有属性name,hashCode都以name计算,hashCode一样,但两个对象属于不同类型,所以equals应为false.
六.为什么需要hashCode?
hashcode是哈希算法的灵魂,通过hashCode可以加快查找速度.理想状态下时间复杂度为O(1)