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

2019-10-10  本文已影响0人  yunqing_71

先来写一个简单的例子:

/**
* 自定义一个钥匙类
*/
@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”

上一篇下一篇

猜你喜欢

热点阅读