hashCode与equals 通过面试题一窥究竟

面试题:
public class User {
    private String id;
    public User(String id) {
        this.id = id;
    }
    @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 != null ? id.equals(user.id) : user.id == null;
    }
    @Override
    public int hashCode() {
        return id != null ? id.hashCode() : 0;
    }
    public static void main(String[] args) {
        Set<User> set = new HashSet<>();
        User u1 = new User("1");
        User u2 = new User("1");
        User u3 = new User("1");
     set.add(u1);
        set.add(u2);
        set.add(u3);
        for (User u:set) {
            System.out.println(u.id);
        }
    }
}
//问题:当User只重写equals   或者 只重写hashcode ,以及同时重写后,当遍历Set结果是什么? 
流程图说明:
那么当存入set 或者map 中的不允许相同数据存入的流程是怎样的呢?见下图
 
以上抛出几个问题
1、hashCode 为什么放在equals 之前?
    equals 的比较是复杂的,重写该方法后,会进行null,空,是否是该对象等等比较,如果先进行hashCode 比较则提升性能,一旦不同即可放入对象
 
2、为什么既要进行hashCode 也要进行equals比较?
          先抛老生常谈的结论:hashCode 值相同 equals 不一定相同,equals 相同,hashCode 一定相同。
     方法介绍:
         equals  :  源码进行了==比较,比较地址!
         hashCode : 通过hash算法计算一个int 值。计算地址!
     原理理解:
          hashCode 和 equals 都是Object 的方法,如果不重写都是对地址进行操作。
         下面根据最上面的面试题来给出理解思路:(为方便讲解粘上部分代码)
      User u1 = new User("1");  User u2 = new User("1");  User u3 = new User("1");
      set.add(u1);  set.add(u2);  set.add(u3);
以下三种情况讲解:
一、不重写hashCode,重写equals:根据流程图 第一步执行hashCode 的判断 由于没有重写hashCode所以对地址进行hash计算 两个对象地址不同直接存入集合。 遍历结果:  1, 1 , 1
 
二、不重写equals,重写hashCode :第一步执行hashCode值相同,往下执行equals 由于未重写equals 所以直接比较地址,两个对象地址不同,直接存入Set集合。  遍历结果:  1, 1 , 1
 
三、同时重写:第一步执行hashCode,值相同,往下执行equals ,重写equals 判断对象相同,舍弃。 遍历结果:  1
 
posted @ 2019-05-05 16:09  蓝色丶格调  阅读(449)  评论(0编辑  收藏  举报