什么时候重写hashcode与equals

论坛 期权论坛 脚本     
匿名技术用户   2021-1-6 10:25   64   0

注:本文的所有验证在文章最后

如果您愿意相信我的话,请静下心来,慢慢阅读,一定会解除您心中的些许疑惑

一、原生的hashCode与equals是什么样的

原生hashCode值为内存地址(未考正)

原生equals比较的是内存地址

二、什么时候重写equals?

答:比较两个实例是否相等时重写equals()。

equals()用于比较两个实例是否相等,两实例属性对应相等 => 两实例相等

只单纯比较两个同类型实例是否相等时只重写equals()就可以。作者觉得 "为什么重写equals()一定要重写hashCode”这种标题并不合理。

三、什么时候重写hashCode?

答:自定义类型作为HashMap的key

我相信还有其他情况需要重写hashCode,作者愚笨,暂时还不了解其他的情况,请谅解。

四、重写hashCode与equals的例子

自定义类型作为HashMap的key,没错,这也是重写hashCode的原因。

讲解如下:

1.HashMap不允许key重复的含义:

请先明确:即使您未重写hashCode与equals,自定义类型作为HashMap的key,从代码上是完全被允许的。

HashMap中不允许key重复指的是逻辑重复,下图中的这种逻辑是不被允许的,但这种逻辑是存在的(不重写hashCode和equals就会导致如下情况,未重写两方法时两个属性相等的实例被视为不等的对象)

图 4-1

2.HashMap判别key是否重复的过程图:

图 4-2

只有重写了hashCode与equals,才能识别出重复的key,从而覆盖。

不重写hashCode与equals或只重写其中的一个,最终的结果都为key不等,无法识别出重复的key。

HashMap在设计时采用hashCode+equals方法为了提高性能,当hashCode不等时就没必要去调用equals来判断key是否重复了

3.源码(JDK1.7,HashMap的 put 方法)

五、验证:

1.原生hahsCde与equals验证:

import java.util.Objects;

/*
* 1.验证hashcode未重写哈希值为地址,即使属性完全相等的对象hshcode值也不同,而我们不需要这样的严格相等所以重写使得hashcode值与属性相关
* 2.验证equals为重写是比较的是内存地址,重写后比较的是属性,只有hsahcode相等两个对象才可能相等,equals相等的对象才彻底相等
*
* */
public class test {
    public static void main(String[] args) {

        //创建两个一模一样的对象
        User user1 = new User(1,"小明");
        User user2 = new User(1,"小明");

        System.out.println("user1的哈希值:"+user1.hashCode());
        System.out.println("user2的哈希值:"+user2.hashCode());
        System.out.println("user1与user2的是否相等:"+user1.equals(user2));
    }
}
class User {
    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

//hashCode与equals方法集成开发环境可自动生成,Intellij请用alt+insert  
/* 
      @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return id == user.id &&
                name.equals(user.name);
    }
*/
    /*@Override
    public int hashCode() {
        return Objects.hash(id, name);
    }*/
}

结果如下:

此时两个属性完全相等的对象的哈希值不等,用equals方法比较结果为false.

2.重写euqals()的验证:

取消上面代码中重写的equals方法注释,执行代码。

结果如下:

3.逻辑冲突验证:

//放到上述main方法中  
Map<User,Integer> map =new HashMap<User,Integer>();

   User user1 = new User(1,"小明");
   User user2 = new User(1,"小明");
   map.put(user1,1);
   map.put(user2,2);
   System.out.println(map.get(user1));
   System.out.println(map.get(user2));

结果如下:

相等的user对应着不同的int值,实际中有时不需要这样的逻辑。

4.解决逻辑冲突(重写hashCode与equals)验证:

请您将User中hashCode与equals方法注释取消再看结果。

结果如下:

此时不再允许key重复了,当再put相同的key值时发生覆盖。

5.您可自行重写hashCode、equals其中的一个来验证图4-2

六、其他

作者愚笨,如有问题请纠正。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP