哈希映射码--------hashCode

返回对象的哈希码值。该值用于哈希码映射计算中,如Hashtable类对对象进行存储、提取等操作就是基于该对象的哈希码的值的。关于哈希码,Java API文档有如下几条常规协定。

·在Java应用程序执行期间,如果在equals方法比较中所用的信息没有被修改,那么在同一个对象上多次调用hashCode方法时,必须一致地返回相同的整数。但如果多次执行同一个应用时,不要求该整数必须相同。

·如果两个对象通过调用equals方法是相等的,那么着两个对象调用hashCode方法必须返回相同的整数。

·如果两个对象通过调用equals方法是不相等,不要求这两个对象调用hashCode方法必须返回不同的整数。但是,程序员应该意识到对不同的对象产生不同的哈希码值可以提高哈希表的性能。

在Object类中,对于不同的对象,hashCode方法会返回不同的哈希码值,该值通常是根据对象的地址计算而来的。

根据协议第二点,当子类重写了equals方法时,一定要同时重写hashCode方法,否则可能会使得哈希表无法正常得到我们期待的效果。

在下例中:

运行结果:

在main方法中定义了两个HashMap,一个以Box1对象为键,一个以String对象为键。可知box1与box2不相等,box1与box3相等,s1与s2不相等,s1与s3相等。

当map2将s1 作为键(key)存储值(value)"value1"后,通过以s3为键也可以取回值"value1",但是当map1将box1作为键存储值"box1"后,通过box3为键却无法将值"box1"返回。

原因很简单,就是因为String类中在重写了equals方法的同时,也重写了hashCode方法,使得当equals方法返回true时,hashCode的值也相等,而Box1类只重写了equals方法。两个Box1类的对象box1与box3虽然相等(equals返回true),但是两个对象的hashCode仍然不同。于是,当对象参与HashMap的存储与提取时,就无法得到期望的结果。

由于String类重写了hashCode方法,使得相等的String对象(以equals方法来判断)的哈希码值也相同,这样,s1与s3也就能够产生相同的哈希码值来计算哈希表的映射地址,以s1作为键在哈希表中存储值,通过s3一样可以成功取得该值。这就好比有两把相同的尺A与B,我们通过A尺在距离门前5m处埋下一箱宝藏,通过B尺测量5m同样可以取出这厢宝藏一样。

Box1类只重写了equals方法,而没有重写hashCode方法,这使得两个相等的Box1对象的哈希码值也不相同(违背了hashCode方法的第二点协定)。Box1类使用的是从Object类继承而来的hashCode方法,而Object类的hashCode方法通常是根据对象的地址来计算哈希码值的,所以不同的对象一般情况下哈希码值也不会相同。

因此,只要在类中重写equals方法,就一定要重写hashCode方法,通常情况下,应该尽量使不同的对象产生不同的哈希码值(第三点协定),而多数对象都是根据成员变量来判断对象是否相同,这就可以使用成员变量来计算哈希码值。

这也意味着,用来计算哈希码值的成员变量应该与equals方法中用来比较对象是否相等所使用的成员变量相同,或者为equals方法的子集。

例如修正上面的例子:

这样一来,使用equals方法判断相等的两个对象在调用各自的hashCode方法时也一定会产生相同的哈希码值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值