第9条:覆盖equals时总要覆盖hashCode

第9条:覆盖equals时总要覆盖hashCode

在每一个覆盖equals方法的类中,都必须覆盖hashCode方法,如果不这么做,会导致这个类无法结合所有基于散列的集合的正常使用,如HashMap,HashSet,Hashtable。

Object规范中有这么一条:

如果两个对象根据equals(Object)方法比较是相等的,那么调用这对象中任意一个对象的hashCode方法都必须产生同样的整数结果。

因为对于两个对象A和B,如果A.equals(B)为true,则代表A与B在逻辑上是相等的,但是Object中的hashcode方法,则是根据对象的内存地址来生成hashcode,这也就会导致两个逻辑上相等的对象的hashcode却是不同的。这在使用基于hashcode的散列表(如HashMap)时会出现问题:

public class PhoneNumber{
    private int areaCode;
    private int prefix;
    private int lineNumber;

    public PhoneNumber(int areaCode,int prefix,int lineNumber){
        this.areaCode = areaCode;
        this.prefix = prefix;
        this.lineNumber = lineNumber;
    }

    @Override
    public boolean equals(Object o){
        if(o == this){
            return this;
        }
        if(!(o instanceof PhoneNumber)){
            return false;
        }
        PhoneNumber pn = (PhoneNumber)o;
        return pn.lineNumber == lineNumber
             && pn.prefix == prefix
             && pn.areaCode == areaCode;
    }
}
Map<PhoneNumber, String> m = new HashMap<PhoneNumber, String>();
m.put(new PhoneNumber(707, 867, 5309), "Jenny");
m.get(new PhoneNumber(707, 867, 5309));    //return null

因为在HashMap中,会先根据传入对象的hashcode找到相应的桶,然后再在桶中寻找相等的对象,换言之如果连两个对象的hashcode都不同,那么也不会去比较这两个对象是否相等。

一个好的hashcode方法将会为不同的对象产生不同的hashcode,在最理想的情况下,应该把集合中所有不相等的对象均匀分布到所有可能的值上。

在hashcode的计算过程中,可以将冗余域(即可以通过参与计算的其它值计算出来的值)排除在外,还有必须排除equals方法中没有的所有值,否则有可能出现两个对象逻辑相等但是生成的不同的状况。

如果一个类中参与hashcode计算的变量都是不可变(final)的,而且hashcode计算的开销又非常大,那么可以在创建这个对象,或第一次使用hashcode时计算这个值,然后将hashcode保存在这个对象内部。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值