面试题(2)-HashMap 是怎么解决哈希冲突的

这篇具有很好参考价值的文章主要介绍了面试题(2)-HashMap 是怎么解决哈希冲突的。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.Hash函数(别名:散列函数,又叫Hash算法)

Hash函数指将哈希表中元素的关键键值映射为元素存储位置的函数。

把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值。

散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。因此,散列值是不可逆的,无法通过散列值确定输入值

简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

常用的Hash算法

  • UUID(Hash Function For Sequence of Unique Ids)
  • MD5(Message-Digest Algorithm 5)
  • SHA(Secure Hash Algorithm)

    Sha1哈希值长度为160位,Sha256为256位,更安全。

常用的Hash函数

1.直接寻址法。

取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数)

2.数字分析法。

分析一组数据,比如一组员工的出生年月日,这时我们发现出生年月日的前几位数字大体相同,这样的话,出现冲突的几率就会很大,但是我们发现年月日的后几位表示月份和具体日期的数字差别很大,如果用后面的数字来构成散列地址,则冲突的几率会明显降低。因此数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址。

3.平方取中法。

取关键字平方后的中间几位作为散列地址。

4.折叠法。

将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(去除进位)作为散列地址。

5.随机数法。

选择一随机函数,取关键字作为随机函数的种子生成随机值作为散列地址,通常用于关键字长度不同的场合。

6.除留余数法。

取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key MOD p,p<=m。不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选的不好,容易产生碰撞。

著名的ELFhash算法

int ELFhash(char*key)
{
    unsigned long h=0;
    while(*key)
    {
        h = (h << 4) + *key++;
        unsigned long g = h & 0xF0000000L;
        if(g)
            h ^= g >> 24;
        h &= ~g;
    }
    return h % MOD;
}

2.Hash表(别名: 散列表)

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

3.Hash 冲突

所谓 hash 冲突,是由于哈希算法被计算的数据是无限的,而计算后的结果范围有限,所以总会存在不同的数据经过计算后得到的值相同,这就是哈希冲突。

无论哈希函数设计有多么精细,都会产生冲突现象,也就是2个关键字(key)处理函数f(key)的结果hashValue映射在了同一位置上,因此,有一些方法可以避免冲突。

4.解决 hash 冲突的方法

  1. 开放定址法,也称为线性探测法

就是从发生冲突的那个位置开始,按照一定的次序从 hash 表中找到一个空闲的位置,然后把发生冲突的元素存入到这个空闲位置中。ThreadLocal 就用到了线性探测法来解决 hash 冲突的。

向这样一种情况(如图),在 hash 表索引 1 的位置存了一个 key=name,当再次添加
key=hobby 时,hash 计算得到的索引也是 1,这个就是 hash 冲突。而开放定址法,
就是按顺序向前找到一个空闲的位置来存储冲突的 key。

  1. 链式寻址法

这是一种非常常见的方法,简单理解就是把存在 hash 冲突
的 key,以单向链表的方式来存储,比如 HashMap 就是采用链式寻址法
来实现的。

向这样一种情况(如图),存在冲突的 key 直接以单向链表的方式进行存储。

  1. 多hash法

就是当通过某个 hash 函数计算的 key 存在冲突时,再用另外一个 hash 函数对这个 key 做 hash,一直运算直到不再产生冲突。这种方式会增加计算时间,性能影响较大。

  1. 建立公共溢出区

就是把 hash 表分为基本表和溢出表两个部分,凡事存在冲突的元素,一律放入到溢出表中。

【注意】HashMap 在 JDK1.8 版本中,通过链式寻址法+红黑树的方式来解决 hash 冲突问题,其中红黑树是为了优化 Hash 表链表过长导致时间复杂度增加的问题。当链表长度大于 8 并且 hash 表的容量大于 64 的时候,再向链表中添加元素就会触发转化。

 

 文章来源地址https://www.toymoban.com/news/detail-630499.html

到了这里,关于面试题(2)-HashMap 是怎么解决哈希冲突的的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java学数据结构(4)——散列表Hash table & 散列函数 & 哈希冲突

    1.散列表,key,散列函数; 2.哈希冲突的解决; 3.string中的hashCode; 查找树ADT,它允许对元素的集合进行各种操作。本章讨论散列表(hash table)ADT,不过它只支持二叉查找树所允许的一部分操作。散列表的实现常常叫作散列(hashing)。散列是一种用于以常数平均时间执行插入、删除和

    2024年02月10日
    浏览(47)
  • OpenCV每日函数 了解不同的图像哈希函数、以及OpenCV的img_hash哈希模块

            图像哈希是 使用算法为图像分配唯一哈希值的过程 。图像的副本都具有完全相同的哈希值。因此,它有时被称为“数字指纹”。         在深度学习普及之前,一些搜索引擎使用散列技术来索引图像。这就需要一个哈希函数,对于文件的微小更改,该函数会

    2024年02月11日
    浏览(43)
  • ThreadLocalMap中hash冲突的解决

    作用是设置当前线程绑定的局部变量: 首先是获取当前线程,并根据当前线程获取一个Map。 如果获取的Map不为空,则将参数设置到Map中(当前ThreadLocal的引用作为key)。这里调用了 ThreadLocalMap 的set方法。 如果Map为空,则给线程创建Map,并设置初始值。这里调用了 ThreadLocal

    2023年04月09日
    浏览(27)
  • 【C++入门到精通】 哈希结构 | 哈希冲突 | 哈希函数 | 闭散列 | 开散列 [ C++入门 ]

    在现代计算机科学和数据结构中,哈希(Hash)是一项重要而广泛应用的技术。通过将输入数据映射为固定长度的哈希值,哈希函数能够快速高效地进行数据存储、搜索和比较。然而,由于输入数据的多样性和哈希值的有限长度,哈希冲突成为了一个不可避免的问题。本文将介

    2024年02月08日
    浏览(31)
  • 【C++杂货铺】一文带你走进哈希:哈希冲突 | 哈希函数 | 闭散列 | 开散列

    在 C++98 中,STL 提供了底层为红黑树结构的一些列关联式容器,在查询时效率可以达到 O ( l o g 2 N ) O(log2^N) O ( l o g 2 N ) ,即最差情况下需要比较红黑树高度次,当树中的结点非常多的时候,查询效率也不理想。最好的查询是,进行很少的比较次数就能够将元素找到,因此在

    2024年02月08日
    浏览(32)
  • 【数据结构与算法】04 哈希表 / 散列表 (哈希函数、哈希冲突、链地址法、开放地址法、SHA256)

    一种很好用,很高效,又一学就会的数据结构,你确定不看看? 莫慌,每个概念都很好理解。 哈希表( Hash Table ),也称为 散列表 ,是一种数据结构, 用于存储键值对(key-value pairs) 。 键值对是一种数据结构,用于将键(key)与对应的值(value)相关联。在键值对中,键

    2024年02月09日
    浏览(63)
  • 什么是redis中的哈希桶、哈希冲突及解决方法

    Redis中的哈希桶是一种数据结构,用于在Redis的哈希表(如字典结构)中存储键值对。 哈希桶是哈希表数组中的每个元素,可以视为一个容器或槽位,用于存放数据。在Redis中,当插入一个新的键值对时,会根据键的哈希值计算出一个索引,该索引指向特定的哈希桶。 每个哈

    2024年04月08日
    浏览(38)
  • 解决哈希冲突的几种方法

    哈希函数是一个映像,把任意长度的输入,通过Hash算法变换成固定长度的输出,这个输出就是Hash值; 当两个不同的输入,产生了同一个输出值即为哈希冲突 开放寻址法的核心思想是, 如果出现了散列冲突,我们就重新探测一一个空闲位置,将其插入 。比如,我们可以使用

    2024年01月17日
    浏览(25)
  • Hash(散列)冲突解决之线性探测再散列和二次探测再散列

    H(key) = key %13,key 为,采用开放地址法中的线性探测再散列解决冲突,依次输入11 个,16,74,60,43,54,90,46,31,29,88,77,构造哈希表 如图,例如 16%13=3,将16放入3号位置,29%13 = 3,将29放入3号位置,而此时3号位已经有元素。 就顺着表往后放,直到6号没

    2024年02月08日
    浏览(32)
  • 【数据结构】 | java中 哈希表及其冲突解决

    🎗️ 博客新人,希望大家一起加油进步 🎗️ 乾坤未定,你我皆黑马 1、哈希表概念 顺序结构以及平衡树中 ,元素关键码与其存储位置之间没有对应的关系,因此在 查找一个元素时,必须要经过关键码的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(Lo

    2024年01月19日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包