hashcode详解

文章概述

本文介绍了Java中hashCode方法的作用和实现原理,以及如何根据对象的内容来自定义hashCode方法。hashCode方法用于获取对象的唯一标识符,返回一个整数值,常用作哈希表等数据结构中快速定位对象的基础。在Java中,所有对象都可调用此方法,其默认实现基于对象的内存地址。为确保equals方法的正确性,自定义类应重写hashCode方法,保证当equals返回true时,hashCode也返回相同值。此外,文中通过示例说明了根据对象属性定制hashCode方法的重要性,并讨论了哈希冲突的概念及解决方案。通过实验数据表明,Java的哈希算法具有较高的安全性,能在大量尝试下有效避免或减少哈希冲突的发生。

关键要点

  1. HashCode是Java中获取对象唯一标识符的方法,用于快速定位对象。
  2. 默认情况下,HashCode方法返回对象的内存地址哈希码表示。
  3. 如果两个对象equals方法返回true,它们的HashCode方法应返回相同值。
  4. 可以通过自定义HashCode方法来生成哈希码,但需保持唯一性和均匀分布。
  5. 哈希冲突可能导致性能下降,需正确实现equals方法来确保对象相等性判断。

前言

HashCode是在Java中用于获取对象的唯一标识符的方法。它是根据对象的内容生成的一个整数值。对象的hashCode()方法被调用时,它返回的是对象的哈希码。哈希码可以用于在哈希表等数据结构中快速定位对象。

在Java中,hashCode()方法是被Object类定义的,所有的对象都可以调用该方法。默认情况下,hashCode()方法返回的是对象的内存地址的哈希码表示。

通常情况下,如果两个对象的equals()方法返回true,那么它们的hashCode()方法应该返回相同的值。这是为了确保在集合类(如HashMap、HashSet等)中能正确地工作。

如果你自定义的类需要使用equals()方法进行对象的比较,那么通常也需要重写hashCode()方法,保证它们的一致性。

你可以使用hashCode()方法来获取对象的哈希码,例如:

public class MyClass {
    private int id;
    private String name;

    // constructors, getters, setters, etc.

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
}

在上面的例子中,hashCode()方法根据对象的id和name属性生成哈希码。这样,当两个对象的id和name属性相同时,它们的hashCode()方法会返回相同的值。

hash是随机生成的吗

哈希码的生成通常是根据对象的内容计算得出的,而不是随机生成的。在Java中,默认的hashCode()方法实现是根据对象的内存地址计算得到的一个整数值。这意味着,对于同一个对象,在其生命周期内,多次调用hashCode()方法应该返回相同的值。

然而,有时候我们会根据对象的内容来自定义hashCode()方法。在这种情况下,哈希码的生成过程可以依赖于对象的属性,并且根据具体的实现方式而有所差异。

重要的一点是,生成的哈希码应该尽可能地保持唯一性和均匀分布,以提高在哈希表等数据结构中的查找效率。这样可以尽量避免哈希冲突(即不同对象生成了相同的哈希码),从而提高性能。

需要注意的是,尽管哈希码是根据对象的内容计算得出的,但它并不保证对象的唯一性。不同的对象可能会生成相同的哈希码,这就是所谓的哈希冲突。为了解决哈希冲突,Java中提供了equals()方法进行对象的比较,当equals()方法返回true时,可以认为两个对象是相等的。

因此,在使用哈希码时,我们既需要考虑哈希码的计算方式,也需要正确实现equals()方法来确保对象的相等性判断。

hash碰撞

Set set = new HashSet();
        int hashCodeValue;

        for (int i = 1; i <= 150000; i++)
        {
            hashCodeValue = new Object().hashCode();

            if(set.contains(hashCodeValue))
            {
                //你新生成的刚好是我hashset里面已经有的,冲突发生....
                System.out.println("发生hash冲突,在第: "+i+" 次,hashCodeValue "+ hashCodeValue);
                continue;
            }else{
                set.add(hashCodeValue);
            }
        }
        System.out.println(set.size());

这段代码创建了一个HashSet并循环生成150,000个对象的哈希码,并将哈希码添加到HashSet中。如果生成的哈希码已经存在于HashSet中,则打印出哈希冲突的信息,继续下一个循环。最后打印HashSet的大小。java中在100000次内一般不会发生hash冲突(碰撞),在110000次中一般会发生一次hash冲突。上面代码中生成了150000次hashcode值,发生了五次冲突。java的安全性还是很厉害的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
(44-李四)覆盖(44-张三)
在这里插入图片描述
在这里插入图片描述
形成链表
在这里插入图片描述
在这里插入图片描述

依次比较
在这里插入图片描述
![请添加图片描述](https://i-blog.csdnimg.cn/direct/414054b0291842e8bc29a749704e6609.jpeg

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值