美文网首页Java
再论:关于 equals 和 hashCode

再论:关于 equals 和 hashCode

作者: shengjk1 | 来源:发表于2020-03-15 12:28 被阅读0次

    上篇 关于 equals 和 hashCode 关于 equals 和 hashCode 的基本性质已经论述过了。

    1.什么时候应该覆盖 equals?
    我们知道 equals 默认比较的内存地址,即是否为同一个对象。如果类具有了自己特有的逻辑相等,即属性值等,的概念时,并且超类没有覆盖或者覆盖了单不满足子类需求的情况下重写 equals。

    但对于类似枚举类这样的 class 而言,每个属性最多只存在一个对象,逻辑相等与内存地址相等时一样的,不需要重写。

    2.为什么要覆盖 equals( hashCode) ?

    /**
     * @author shengjk1
     * @date 2020/3/14
     */
    public class TestEquals {
        public static void main(String[] args) {
            HashMap<Student, String> map = new HashMap<>();
            Student student = new Student(16, "小明");
            map.put(student, "a");
            Student student1 = new Student(16, "小明");
            System.out.println(map.containsKey(student1));
        }
    }
    
    class Student {
        private int age;
        private String name;
        
        public Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
        
        public int getAge() {
            return age;
        }
        
        public void setAge(int age) {
            this.age = age;
        }
        
        public String getName() {
            return name;
        }
        
        public void setName(String name) {
            this.name = name;
        }
        
        //  @Override
    //  public boolean equals(Object o) {
    //      if (this == o) return true;
    //      if (o == null || getClass() != o.getClass()) return false;
    //      Student student = (Student) o;
    //      return age == student.age &&
    //              Objects.equals(name, student.name);
    //  }
    //
        @Override
        public int hashCode() {
            return Objects.hash(age, name);
        }
    }
    

    结果

    false
    

    这完全不是我们想要的,我们希望的是 map.containsKey(student1) 为true。但为什么是 false 呢?通过源码我们可以知道 应为 equals 不等,导致的。同理,对于 hashCode 也是如此。

    3.是否是任何时候都需要覆盖 equals 和hashCode?
    答案是 否定的。
    还记得上一篇说过的吗,JDK 内部就有违背 equals hashCode 一致性规则的。另外的话,hashCode 仅仅针对 hash 表来说才有用。

    /**
     * @author shengjk1
     * @date 2020/3/14
     */
    public class TestEquals {
        public static void main(String[] args) {
            HashMap<Student, String> map = new HashMap<>();
            Student student = new Student(16, "小明");
            map.put(student, "a");
            Student student1 = new Student(16, "小明");
            System.out.println("map " + map.containsKey(student1));
            
            ArrayList<Student> students = new ArrayList<>();
            students.add(student);
            System.out.println("list " + students.contains(student1));
        }
    }
    
    class Student {
        private int age;
        private String name;
        
        public Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
        
        public int getAge() {
            return age;
        }
        
        public void setAge(int age) {
            this.age = age;
        }
        
        public String getName() {
            return name;
        }
        
        public void setName(String name) {
            this.name = name;
        }
        
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Student student = (Student) o;
            return age == student.age &&
                    Objects.equals(name, student.name);
        }
    //
    //  @Override
    //  public int hashCode() {
    //      return Objects.hash(age, name);
    //  }
    }
    

    结果

    map false
    list true
    

    对于 list 而言,根本就不需要 比较hashCode,我们也违背了 equals 与 hashCode 的一致性,但对于 students.contains(student1) 结果就是正确的

    4.总结
    1.java 集合内部比较对象是否相等一般用的都是 equals ,所以 equals 是要尽量重写的。
    2.而对于 hashCode 来说,对于 hash table 来说是必须要重写的,其他的可以不重写。

    相关文章

      网友评论

        本文标题:再论:关于 equals 和 hashCode

        本文链接:https://www.haomeiwen.com/subject/qnshehtx.html