为什么要重写equals和hashcode方法

为什么重写equals方法还要重写hashcode方法

举例说明

只重写equals方法

class B {
    private String name;
    public B(String name) {this.name = name;}
    public boolean equals(Object o) {
        if (this == o) return true;
        B b = (B) o;
        return name == b.name;
    }
}
B b1 = new B("1");
B b2 = new B("1");
System.out.println(b1.equals(b2)); // true
System.out.println(b1.hashCode()); // 460141958
System.out.println(b2.hashCode()); // 1163157884
// 会发现,它们内容相同了,但是hash值却不相同
// 如果这时使用B类元素来作为Map集合的key,那么map中就会存在重复内容的元素
// 因为map是跟据hash来计算索引位置的,而这时它们的hash值不相同,所以可以直接添加到map集合中(hash不同索引位置不同)
【跟据hash来计算索引位置是java开发者为了减少hash冲突概率的一种算法】

只重写hashcode方法

class C {
    private String name;
    public C(String name) {
        this.name = name;
    }
    public int hashCode() {
        return Objects.hash(name);
    }
}
C c1 = new C("1");
C c2 = new C("1");
System.out.println(c1.hashCode()); // 80
System.out.println(c2.hashCode()); // 80
System.out.println(c1.equals(c2)); // false
/*
	可以看出上面hash值相同了,但是equals比较它们却不相同,默认equals方法比较的是内存地址
	假设现在用C类元素作为hashMap集合的key,c1已经添加到容器中了,这时添加c2,当它们判断到它们key相同时,就会继	  续调用C类中的equals方法来比较 因为没有重写,所以比较的是c1和c2的内存地址,因为不同,所以添加成功了。
	但是这种情况下是不允许的,为什么。
	因为它们的内容 name属性都是"1", 从人类思维上来说,它们的内容是一样的啊,按理说一样的属性equals应该判断为
	true才对,但是因为equals方法默认比较的是内存地址
	所以这个时候需要重写equals方法来比较它们的name属性是否相同。这个时候计算机就知道c1和c2它们的内容是相同的
*/

重写equals和hashcode方法

class D {
    private String name;
    public D(String name) {this.name = name;}
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        D d = (D) o;
        return name == d.name;
    }
    public int hashCode() {
        return name.hashCode();
    }
}
D d1 = new D("1");
D d2 = new D("1");
System.out.println(d1.equals(d2)); // true
System.out.println(d1.hashCode()); // 49
System.out.println(d2.hashCode()); // 49
/*
	在重写了两个方法后,我们来用D类作为hashMap的key来使用
	当d1添加进去后,又添加了d2时,这时会通过hash值计算出当前元素在容器中的索引位置,因为hash值相同,所以在d1	
	添加的时候,假设它的索引位置时4,这时d2也通过计算后其索引也为4,这时就会判断d1和d2的hash值是否相同,相同则		继续比较它们的内容是否相同,就会调用D类中的equals方法,比较的是它们内部的name属性是否相同,又因为name属性是
	字符串类型,所以"1"值指向都是常量池中同一个对象,最后执行 return name == d.name; 比较后发现它们的name属性	相同,所以hashmap就会认为当前要添加的元素的key在容器中已经存在,那么就会将新的元素覆盖掉容器中已存在的元素。
*/

结论:在确保不允许有重复元素的情况下,必须重写两个方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值