打字猴:1.700442282e+09
1700442282 编写高质量代码:改善Java程序的151个建议 [:1700438117]
1700442283 编写高质量代码:改善Java程序的151个建议 建议48:覆写equals方法必须覆写hashCode方法
1700442284
1700442285 覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先来看如下代码:
1700442286
1700442287 public static void main(String[]args){
1700442288
1700442289 //Person类的实例作为Map的key
1700442290
1700442291 Map<Person, Object>map=new HashMap<Person, Object>(){
1700442292
1700442293 {
1700442294
1700442295 put(new Person(“张三”),new Object());
1700442296
1700442297 }
1700442298
1700442299 };
1700442300
1700442301 //Person类的实例作为List的元素
1700442302
1700442303 List<Person>list=new ArrayList<Person>(){
1700442304
1700442305 {
1700442306
1700442307 add(new Person(“张三”));
1700442308
1700442309 }
1700442310
1700442311 };
1700442312
1700442313 //列表中是否包含
1700442314
1700442315 boolean b1=list.contains(new Person(“张三”));
1700442316
1700442317 //Map中是否包含
1700442318
1700442319 boolean b2=map.containsKey(new Person(“张三”));
1700442320
1700442321 }
1700442322
1700442323 代码中的Person类与上一建议相同,euqals方法完美无缺。在这段代码中,我们在声明时直接调用方法赋值,这其实也是一个内部匿名类的操作(下一个建议会详细说明)。现在的问题是b1和b2这两个boolean值是否都为true?
1700442324
1700442325 我们先来看b1,Person类的equals覆写了,不再判断两个地址是否相等,而是根据人员的姓名来判断两个对象是否相等,所以不管我们的new Person(“张三”)产生了多少个对象,它们都是相等的。把“张三”对象放入List中,再检查List中是否包含,那结果肯定是true了。
1700442326
1700442327 接着来看b2,我们把张三这个对象作为了Map的键(Key),放进去的对象是张三,检查的对象还是张三,那应该和List的结果相同了,但是很遗憾,结果是false。原因何在呢?
1700442328
1700442329 原因就是HashMap的底层处理机制是以数组的方式保存Map条目(Map Entry)的,这其中的关键是这个数组下标的处理机制:依据传入元素hashCode方法的返回值决定其数组的下标,如果该数组位置上已经有了Map条目,且与传入的键值相等则不处理,若不相等则覆盖;如果数组位置没有条目,则插入,并加入到Map条目的链表中。同理,检查键是否存在也是根据哈希码确定位置,然后遍历查找键值的。
1700442330
1700442331 接着深入探讨,那对象元素的hashCode方法返回的是什么值呢?它是一个对象的哈希码,是由Object类的本地方法生成的,确保每个对象有一个哈希码(这也是哈希算法的基本要求:任意输入k,通过一定算法f(k),将其转换为非可逆的输出,对于两个输入k1和k2,要求若k1=k2,则必须f(k1)=f(k2),但也允许k1≠k2,f(k1)=f(k2)的情况存在)。
[ 上一页 ]  [ :1.700442282e+09 ]  [ 下一页 ]