覆盖equals时总要覆盖hashCode

在每一个覆盖了equals方法的类中,也必须覆盖hashcode方法。如果不这么做的话,就会违反Object.hashcode的通过约定,

从而导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap,HashSet和HashTable.

Object默认的hashCode是按地址所在的位置返回数据的,所以只要不是同一个对象,就会产生不同的结果,刚好和本身的equals方法吻合。

我们先做个测试,看看有什么问题:

public class PhoneNumber {
    private final short areaCode;
    private final short prefix;
    private final short lineNumber;
    public PhoneNumber(int areaCode,int prefix,int lineNumber){
        rangeCheck(areaCode,999,"area code");
        rangeCheck(prefix,999,"prefix");
        rangeCheck(lineNumber,9999,"line number");
        this.areaCode=(short)areaCode;
        this.prefix=(short)prefix;
        this.lineNumber=(short)lineNumber;
    }
    private static void rangeCheck(int arg,int max,String name){
        if(arg<0||arg>max){
            throw new IllegalArgumentException(name+":" +arg);
        }
    }
    @Override
    public boolean equals(Object o){
        if(o==this)
            return true;
        if(!(o instanceof PhoneNumber))
            return false;
        PhoneNumber pn=(PhoneNumber)o;
        return pn.getLineNumber()==lineNumber&&pn.getPrefix()==prefix&&pn.getAreaCode()==areaCode;
    }

    public short getPrefix() {
        return prefix;
    }

    public short getLineNumber() {

        return lineNumber;
    }

    public short getAreaCode() {

        return areaCode;
    }
    public String toString(){
        return "["+areaCode+","+prefix+","+lineNumber+"]";
    }
}

测试:

public class Test {
    public static void main(String[] args){
        Map<PhoneNumber,String> m=new HashMap<>();
        m.put(new PhoneNumber(707,867,5309),"Jenny");
        System.out.println(m.get(new PhoneNumber(707,867,5309)));
    }
}
我们理想的结果是返回Jenny,但是并不会,了解散列表的人就知道,散列表是依据散列码来存值的,不过散列码不相同,

就存在不同的桶中,当然就找不到了,所以,我们可以复写hashCode,来把我们认为相等的值返回相同的散列值,这样就

可以在hash表中找到我们想要的值。

private volatile int hashcode;
@Override
public int hashCode() {
    int result=hashcode;
    if(result==0){
        result=17;
        result=31*result+areaCode;
        result=31*result+prefix;
        result=31*result+lineNumber;
        hashcode=result;
    }
    return hashcode;
}
再次测试:

Jenny

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值