惭愧,今天看了jdk源码,才彻底明白为什么覆盖了equals()也要覆盖hashCode()

当我们重写了对象的equals方法,一般情况下(这里我指这些对象不需要放到Set或Map中仅仅是比较需要,或者虽然放到Set或Map中,但是get和set时用的是同一对象)是没有问题的,但是,有些情况下就不同了;举个例子

public class Person(){

private int id;

private String name;

//define getter and setter here, omited

 

public void equals(Object obj){

if (!(obj instanceof Person))
            return false;
 return super.equals(obj) && ((Member) obj).getId() == this.getId();

}

}

上述class中没有覆盖hashCode方法,因此这个时候用的是Object.hashCode()的返回值;我们来测试一下

public class TestHashCode extends TestCase {
    
        public void testMap() {
        Person p1 = new Person(1,"aaa"),p2 = new Person(1,"bbb");
        Map map = new HashMap();
        map.put(p1,p1);
        Member value = (Person)map.get(p2);
        System.out.println(value.getName());
    }

}

请注意,这两个对象是相等的,可以从equals()的定义看出来;运行TestHashCode ,结果是NullPointerException;

现在添加hashCode()到Person中

 public int hashCode() {
       
        return this.getId() * 37 ;
    }

重运行TestHashCode ;huh,我们想要的结果出现了,“aaa”

为什么,老早的时候我就问过自己,只怪自己不求甚解;其实很简单

Map.put(key,value)时根据key.hashCode生成一个内部hash值,根据这个hash值将对象存放在一个table中

Map.get(key)会比较key.hashCode和equals方法,当且仅当这两者相等时,才能正确定位到table;

回到先前的问题,为什么添加person.hashCode()前,得不到person对象;因为java中默认的hashCode是根据对象的地址计算得到的,虽然p1.equals(p2)=true,但是p1,p1有不同的内存地址,所以有不同的hashCode;所以通过p2是不能得到value的,这个时候value==null;添加hashCode()后,两个对象有相同hashCode,所以能得到

java中Set是通过Map实现的,所以Map和Set的所有实现类都要注意这一点

HashMap是通过链地址法解决hash collision的,并且新对象都是添加到表头的(这个看了好久才明白,数据结构都还老师了)

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值