equals和hashcode

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)
原文地址:https://www.cnblogs.com/INnoVationv2/p/12820417.html