Object 的 equal() 、hashCode()方法说起

之前对这两个方法感觉很平常,不知道有啥作用,在复习java 容器类的时候我知道其奥秘了。

HashSet 、HashMap如何判断集合元素和map中的key不重复?

由于hashSet内部实现就是HashMap的key,所以分析HashMap就可以了。会先检查对象的HashCode 是否和集合中的已有的重复与否,不同表示不重复,若相同在调用equals 进行比较,true 表示重复,false 不重复。

那就分析HashCode :假如自定义实体类没有重写Object的方法,默认会用Object的方法,而Object的HashCode的比较就是比较对象地址。

equals() : 这个方法是 

public boolean equals(Object obj) {
    return (this == obj);
}

也是比较对象是否相等,即地址是否相等。

问题?

自定义对象People 

public class People {

    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public People(String name) {
        this.name = name;
    }

然后测试:

    public static void main(String[] args) {
        People people1 = new People("sjh");
        People people2 = new People("sjh");

        HashSet<People> hashSet = new HashSet<>();
        hashSet.add(people1);
        hashSet.add(people2);

        System.out.println(hashSet.size());

其打印结果为 2

假如HashSet 表示班级,new People 表示学生,那相当于王班级里装了2次同一个人(不考虑同名的学生),遇到这种情况,我们应该重新修改一下People 类?

即重写equals和 hashCode ();加入代码

   @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof People)) return false;
        People people = (People) o;
        return Objects.equals(getName(), people.getName());
    }

    @Override
    public int hashCode() {

        return Objects.hash(getName());
    }

再次运行就会打印 1 。 再次分析,先看hashCode方法,我们针对名称,而不是对象,这样其名称相同,说明不符合装入set的要求。再看equals(),点击HashMap的源码,会发现如下代码

由于(k = p.key) == key比较的是两个对象的地址,所以自然是false,接着就进入key != null && key.equals(k)的判断,而由于Student类中没有equals方法,所以这里调用的是Object类中的equals方法,而通过查找我们发现,Object类中的equals方法比对的仍然是对象的地址,这样返回的结果还是false,那么我们之前所做的努力就白费了,所以当我们重写了People的equal方法后就会按照我们写的来。运行  return Objects.equals(getName(), people.getName()); 会返回true 表示对象相同,这样就装入set失败。

这样就明白了。


参考文章:https://blog.csdn.net/GaoYan__Ze/article/details/81674079

https://blog.csdn.net/mgl934973491/article/details/71169659

猜你喜欢

转载自blog.csdn.net/sjh_389510506/article/details/88692509