重写equals()方法之后,为什么要重写hashCode()方法?

          我们在学习引用类型变量String时,学习到了String类中重写了equals()方法,用于比较两个字符串的值,引起疑问,为什么String类中要重写equals()方法呢?

        Object类中定义的equals()方法与我们熟知的基本类型变量中的 ' == ' 作用是相同的,都是用于比较对象的地址,而String类型的变量中,重写了equals()方法,重写后的equals()方法用于比较字符串对象的值,在这里,String类在重写了equals()方法后又重写了hashCode()方法,以保证equals()方法返回true时,两个字符串对象的hashCode也相同。

        为什么要保证hashCode也相同呢?

        这不得不提一下hashCode 和 hash表了,在我们创建对象时,根据对象的地址(内存中),通过hash算法会得到一个hashCode值,这个hashCode值就是此对象在hash表中的地址(hash表),比如一个新对象 people1 它在内存中的地址为1111,通过hash算法计算后,得到people1在hash表中的地址为1,也就代表着people1的hashCode=1(这里只是举一个例子,不必纠结people1的内存地址为什么转化为hashCode之后等于1),这里对象的真实地址通过hash算法得到的hashCode有可能相同,也就是说,创建多个对象,可能有多个对象的hashCode=1;如果要系统要调用这个对象,首先,查询hash表的hashCode值,这个时候,会发现,有好多对象的hashCode的值与要调用的对象的hashCode值相等,这个时候就要调用Object类中的equals()方法,将要调用的对象的真实地址与与之hashCode相等的对象的真实地址进行比较,从而找出要调用的对象。

        同理,如果  a1.equals(a2) = true;  就证明a1与a2的真实地址一样,此时a1和a2的hashCode一定相等。

        所以,如果重写了equals()方法,hashCode()方法也必须重写,看个例子

public class A{
    private a1 = 1;
    private a2 = 2;

    @Override
    public boolean equals(Object obj){
        //传入对象obj是否为A的实例
        if(obj instanceof A){
            //因为是A的实例,所以强转为A
            A obj1 = (A) obj;
            if(this.a1 == obj1.a1 && this.a2 == obj.a2){
                return true;
                }
            }
        return false;
    }
    public static void main(String[] args){
        A a1 = new A();
        A a2 = new A();
        System.out.println(a1.hashCode());//2065786090
        System.out.println(a2.hashCode());//1026568466
        System.out.println(a1.equals(a2));//true
    }
}

该例子可以看出,如果不重写hashCode()方法,在equals()方法返回true时,a1和a2的hashCode不同。

        可不可以不重写hashCode()方法?

        答案肯定时不可以的,因为Java 对于 eqauls 方法和 hashCode 方法是这样规定的:(1)如果两个对象相同(equals 方法返回 true),那么它们的 hashCode 值一定要相同;(2) 如果两个对象的 hashCode 相同,它们并不一定相同。当然,你未必要按照要求 去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现 在 Set 集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统, 如果哈希码频繁的冲突将会造成存取性能急剧下降)。

你可能感兴趣的:(java,hash)