美文网首页
你有没有重写过hasCode()和equals()方法?

你有没有重写过hasCode()和equals()方法?

作者: yunqing_71 | 来源:发表于2019-10-10 18:23 被阅读0次

    先来写一个简单的例子:

    /**
    * 自定义一个钥匙类
    */
    @Getter
    @Setter
    @AllArgsConstructor
    class Key{
        private Integer id;
        private String name;
    }
    
    @Test
        public void test4() {
            Key k1 = new Key(1, "锁A的钥匙1");
            Key k2 = new Key(1, "锁A的钥匙2");
            Map<Key, String> map = new HashMap<>();
            map.put(k1, "我能打开锁A");
            System.out.println(map.get(k2));
        }
    

    如上面代码所示:实例化两把钥匙,这两把钥匙都是能打开锁A的钥匙,从实际角度出发,以上程序好比我用钥匙k1来锁门,然后用钥匙k2来打开门,这是符合逻辑的。但是输出结果却不是 我能打开锁A,而是null

    仔细分析,原因有两个:一是没有重写hasCode方法,二是没有重写equal方法
    当我们把k1 放入hashmap中的时候,首先会调用Key类的hascode方法计算hash值,然后把k1放到hash值所指引的内存位置。但是Key类中并没有重写hashCode方法,所以会调用Object类的hasCode方法,所以在输出的时候,取k2的value值得时候,也会走Object的hasCode(),因为k2和k1是两个不同的对象,所以内存地址肯定不一样,所以用k2的hash值肯定获取不到k1的value.

    接下来在Key类上重写hasCode()

    @Getter
    @Setter
    @AllArgsConstructor
    class Key{
    
        private Integer id;
        private String name;
    
        /**
         * 重写hasCode,根据key的id进行hash计算,确保k1和k2存放在同一个内存地址
         * @return
         */
        @Override
        public int hashCode() {
            return id.hashCode();
        }
    
    }
    
    

    上面的代码我们重写了hasCode()但是输出的结果还是null,
    这是因为还没有重写equals()方法,因为hashMap是用链地址法处理哈希冲突的,所以在这个内存位置,可能存在多个链表形式存储的对象,例如锁B的钥匙经过hash计算也应该放在这个内存地址,所以虽然通过k2能够找到这个位置的k1但是并不能确定k1就是和k2能打开同一把锁,因为这里会调用Object的equals方法去判断,所以k1和k2肯定不相等。这就需要重写equals认为只要两个对象都是Key类型,并且id相等,就认为他们相等;

    @Getter
    @Setter
    @AllArgsConstructor
    class Key{
    
        private Integer id;
        private String name;
    
        /**
         * 重写hasCode,确保k1和k2存放在同一个内存地址
         * @return
         */
        @Override
        public int hashCode() {
            return id.hashCode();
        }
    
        /**
         * 如果不重写equals方法,可能两把不同锁的钥匙有同一个hasCode值而已,并不确定这两把钥匙是同一个锁的
         * 所以要重写equals方法判断是否是同一个锁的钥匙
         * @param obj
         * @return
         */
        @Override
        public boolean equals(Object obj) {
            if (obj == null || !(obj instanceof Key)) {
                return false;
            }else {
                /**
                 * 重写方法规定id相等就是同一把锁的钥匙
                 */
                return this.getId().equals(((Key) obj).getId());
            }
        }
    }
    
    

    重写equals方法之后,就可以得到相应的值了,输出 “我能打开锁A”

    相关文章

      网友评论

          本文标题:你有没有重写过hasCode()和equals()方法?

          本文链接:https://www.haomeiwen.com/subject/ymmapctx.html