对象的HashCode值生成依据是什么?

我们都知道,HashSet和HashMap的存储形式都是: 哈希表+链表/红黑树
以HashMap为例,相同哈希值的数据产生哈希冲突,以链表或红黑树的形式存储。为确保Map中不含有重复元素,需要重写数据类的equals()方法以及HashCode()方法。
当重写HashCode方法时,向Objects.hash()中传入的参数就是生成HashCode的依据。

public class Person {
    private String name;
    private int age;
    private int height;

    public Person() {
    }

    public Person(String name, int age, int height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
} 

这里的参数只有name和age,那么在创建Person对象时,只要name值和age值相等,那么两者的HashCode值就相等。

public class HashCodeTest {

    public static void main(String[] args) {
        Person p1 = new Person("cky",21,174);
        Person p2 = new Person("cky",21,175);

        int i1 = p1.hashCode();
        int i2 = p2.hashCode();

        System.out.println(i1 == i2); //true
    }
}

因为HashCode值相等,所以在两个Person对象在向HashMap中存储时就会产生哈希冲突,这时会判断equals方法,如下代码所示。

public class HashCodeTest {

    public static void main(String[] args) {
        Person p1 = new Person("cky",21,174);
        Person p2 = new Person("cky",21,175);

        HashMap<Person,String> map = new HashMap<>();
        map.put(p1,"666");
        map.put(p2,"999");

        Set<Map.Entry<Person, String>> set = map.entrySet();
        for (Map.Entry<Person, String> entry : set) {
            Person key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "-->" + value);
        }
    }
}

因为equals方法的比较标准同样为name和age,所以p1和p2被认定为同一元素,即key值相等,那么在添加<p2, “999”>键值对时,就会对<p1, “666”>键值对中的values值进行覆盖,而key值却不发生改变,仍为p1,这时键值对为<p1, “999”>,遍历结果为:
测试结果1
那么如何“骗过”equals方法,从而使得p1和p2都能成功得添加成功而不被认定为重复元素呢?这里我们重写Person类中的equals方法。

       @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return age == person.age &&
                    height == person.height;
        }

以上将判断是否相同的标准改为age和height(HashCode的生成标准仍为name和age),再次运行测试类,此时的遍历结果就发生了改变。
测试结果2
通过本次测试,我们可以得出答案,不同对象的HashCode值可以相等。通过本测试还理清了HashMap的判别机制,以上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值