多语言展示
当前在线:238今日阅读:84今日分享:32

重写equals方法时必须重写hashcode

实际生活工作中,有些业务需要对Javabean属性值进行判断是否相等,如果按原生的equals比较肯定不行,因为原生的equals只是单纯的比较地址。
工具/原料
1

电脑

2

jdk,idea

方法/步骤
1

如果重写的时候不重hashcode方法会怎么样呢?下面举个简单的例子:public class Test {      public static void main(String[] args) throws Exception {         Person per1 = new Person('zhangsan',12);         Person per2 = new Person('zhangsan',12);         System.out.println(per1.equals(per2));     } }class Person{     private String name;     private int age;     @Override     public boolean equals(Object o) {         if (this == o) return true;         if (o == null || getClass() != o.getClass()) return false;          Person person = (Person) o;          if (age != person.age) return false;         return name.equals(person.name);     }     public Person() {     }     public Person(String name, int age) {         this.name = name;         this.age = age;     }     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     public int getAge() {         return age;     }     public void setAge(int age) {         this.age = age;     }    @Override     public String toString() {         return 'Person{' +                 'name='' + name + '\'' +                 ', age=' + age +                 '}';     } }

3

别急,我们来看接下来的代码实例:public static void main(String[] args) throws Exception { //        Person per1 = new Person('zhangsan',12); //        Person per2 = new Person('zhangsan',12); //        System.out.println(per1.equals(per2));         Map map = new HashMap<>();         map.put(new Person('zhangsan',12), 'student');         System.out.println('输出的结果' + map.get(new Person('zhangsan',12)));     }我们定义了一个map,并将Person作为key,重写完equals之后,map.get(new Person('zhangsan',12))我们期望的是返回一个student值。但是程序的结果返回的值却与期望值大相径庭,程序的结果为null;

4

为何会出现这种与自己想象中的结果大相径庭呢?这是因为Person类没有覆盖hashCode方法,导致两个相同的实例具有不相等的散列码(hash code),违背了hashCode的约定。map的put方法把person对象存在一个散列桶(hash bucket)中,然而get却在另外的一个散列桶中找对象,结果可想而知。就算一个偶然让两个实例正好放到了同一个散列桶中,返回值依然不会变,这跟HashMap的一项优化有关,他会将每个项的散列码缓存起来,如果不匹配就不会去检查他们的对等性,所以返回的依然是null。

5

那么重写重写hashCode后结果会跟自己预期的一样吗?我们来试验一下:public class Test {      public static void main(String[] args) throws Exception { //        Person per1 = new Person('zhangsan',12); //        Person per2 = new Person('zhangsan',12); //        System.out.println(per1.equals(per2));         Map map = new HashMap<>();         map.put(new Person('zhangsan',12), 'student');         System.out.println('输出的结果' + map.get(new Person('zhangsan',12)));     } }  class Person{     private String name;     private int age;      @Override     public boolean equals(Object o) {         if (this == o) return true;         if (o == null || getClass() != o.getClass()) return false;          Person person = (Person) o;          if (age != person.age) return false;         return name.equals(person.name);     }      @Override     public int hashCode() {         int result = name.hashCode();         result = 31 * result + age;         return result;     }      public Person() {     }      public Person(String name, int age) {         this.name = name;         this.age = age;     }      public String getName() {         return name;     }      public void setName(String name) {         this.name = name;     }      public int getAge() {         return age;     }      public void setAge(int age) {         this.age = age;     }      @Override     public String toString() {         return 'Person{' +                 'name='' + name + '\'' +                 ', age=' + age +                 '}';     } }

6

结果为student,跟预期一样。

注意事项

养成编程习惯非常重要,重写完equals第一反应就是要重新hashCode以防忘记。

推荐信息