Posts /

重写equals还要重写hashcode

18 Jul 2020

重写equals还要重写hashcode


参考:

为什么要重写hashcode和equals方法?你能说清楚了吗

主要是因为自定义变量在存入HashMap的时候会用到ha’shCode();

HashMap

在HashMap中如果要比较key是否相等,要同时使用这两个函数。

比较过程:

put的时候需要比较是否有相同的Key。

先求出Key的hashCode(),比较两个值是否相等,若相等再比较equals(),若相等则认为这两个Key是同一个。若hashCode()相等,但equals()不相等,则也认为他们不相等。

因此,如果需要将自定义的变量作为HashMap的key存入,则必须重写两个函数。同时从面向对象来看,如果你希望代表同一个实体的两个对象的hashCode()也是一样的,那么也必须重写hashCode();

HashMap,比较的依据

hashCode()的规则

  • 两个对象相等,hashCode()一定相等。

  • 两个对象不等,hashCode()不一定不等。

  • hashCode()相等,两个对象不一定相同。

  • hashCode()不等,两个对象一定不相同。

测试例子

public class JavaEqual {
    public static void main(String[] args) {

        /*********************************
         * equals与hashcode测试
         *********************************/
        out("equals与hashcode测试");
        Student aStudent = new Student("me");
        Student bStudent = new Student("me");

        if (aStudent.equals(bStudent)) {
            System.out.println("aStudent == bStudent (using customed equal function)");
            System.out.println("aStudent.hashcode " + aStudent.hashCode());
            System.out.println("bStudent.hashcode " + bStudent.hashCode());
        }

        HashMap<Student, String> map = new HashMap<>(3);

        map.put(aStudent, "a");

        String getBstudent = map.get(bStudent);
        /* 为什么需要用bStudent来获取map中的数据呢,因为这两个数据都是一样的
        (或者说代表同一个现实对象中的实体),应该对应同一个实体,
        所以从map中取数据应该也是一样的。*/
        
        /* 如果不重写hashCode(),那么上面这句话会返回null。*/
        
        /* 如果重写了hashCode(),迫使两个对象hashCode相同,但是equals()不同,
           也无法获得出同一个对象。(原因:hashCode相等,不一定是同一个对象);*/
        
        System.out.println("using bStudent get aStudent's value:" + getBstudent);
        outEnd();

        /**************** END **************/
    }
    public static void out(String message) {
        System.err.flush();
        System.out.flush();
        System.out.println("/*********************************\n" + " * " + message + "\n"
                + " *********************************/");
        System.err.flush();
        System.out.flush();
    }
    public static void outEnd() {
        System.err.flush();
        System.out.flush();
        System.out.println("/**************** END **************/\n\n");
        System.err.flush();
        System.out.flush();
    }
}