hash-3.hashCode

1、有一个类Person,有两个字段age和name,我重写Object类的equal方法来比较两个对象的age和name是否相等,
但是不重写hashCode。

package com.hash;

public class Person {
    private Integer age;
    
    private String name;
    
    

    public Person() {
        super();
    }
    
    
    public Person(Integer age, String name) {
        super();
        this.age = age;
        this.name = name;
    }


    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age == null) {
            if (other.age != null)
                return false;
        } else if (!age.equals(other.age))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    
    
}
View Code

场景类

Person p1 = new Person(21,"tom");
Person p2 = new Person(21,"tom");
System.out.println(p1.equals(p2));

这样比较发现打印出来是true。然后执行下面的代码:

HashMap<Person,Integer> hp = new HashMap<Person,Integer>();
hp.put(p1, 10);
System.out.println(hp.get(p2));

发现打印出来是null,原因分析:

因这p1和p2只是逻辑上相等,但是它们的hashCode不相等,而hashMap往里面put对象的时
候,先获取key的hashcode,再往hash表中存数据
Person类没有重写hashCode方法,所以默认使用父类Object类的hashCode方法,是根据内存算的hashCode
,而p1和p2是在堆上new出的两个对象,二者的内存地址肯定不等,所以hashCode肯定不等,所以获取出来是null
要解决这个问题,只有重写hashCode方法,以确保当两个对象相同时,二者的hashCode必须相同

    @Override
    public int hashCode(){
        Integer prime = 31;
        return prime*age.hashCode() + prime*name.hashCode();
    }

重写hashCode方法后,再执行,发现打印出了10

2、

如果两个对象相同,那么二者hashCode必定相同,而hashCode相同,对象却不一定相同,因为散列函数计算hashCode的时候
可能会发生碰撞,如

hash类,我在这个类的hashCode方法里计算hashCode时,只是让age和name相加,这种hash算法,碰撞的机率非常大

package com.hash;

public class Hash {
    private Integer age ;
    
    private Integer name;

    public Hash(Integer age, Integer name) {
        super();
        this.age = age;
        this.name = name;
    }

    public Hash() {
        super();
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getName() {
        return name;
    }

    public void setName(Integer name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        return prime*age+prime*name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Hash other = (Hash) obj;
        if (age == null) {
            if (other.age != null)
                return false;
        } else if (!age.equals(other.age))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    
    
}
View Code

场景类

//这就是hashCode产生碰撞,二者hashCode相同,而对象并不相等
        Hash ha1 = new Hash(11,12);
        Hash ha2 = new Hash(12,11);
        
        System.out.println(ha1.equals(ha2));
        System.out.println("h1 hashCode="+ha1.hashCode()+",h2 hashCode="+ha2.hashCode());

虽然两个对象的hashCode相等,但是两个对象并不相等。

综上

(1)如果重写equal方法,则必须重写hashCode方法。

(2)两个对象相等,则二者hashCode必然相等。

(3)两个对象的hashCode相等,两个对象未必相等,因为计算的hashCode可能会碰撞。

原文地址:https://www.cnblogs.com/fubaizhaizhuren/p/5104842.html