浅谈哈希函数

1.JDK 1.8之前的哈希表

在这里插入图片描述
在这里插入图片描述
上图解析哈希算法:哈希表就是将(key-value)通过哈希算法演算出来。首先通过哈希算法将key生成哈希值(哈希值必须是整数),再让key的哈希值和数组的大小(table.length)进行相关运算,得出上图的索引值,1.8之前的table里存放数组桶下标(索引值)和value(数据)。
这就是key—>value.

2. 解决哈希冲突

哈希冲突:相同的key或者不同的key,通过哈希算法进行相关运算,可能得到相同的索引值,hash(key1)=hash(key2),对于之后查找数据带来冲突,因为不是一个索引对一个数据了,而是一个索引对多个数据。

解决办法:
1.开放定址法:按照一定规则向其他地址探测,直到遇到空桶。这里可以有线性向下探测平方探测(12,22…92…n2)
(1)线性向下探测: Rose和Jack经过哈希算法相关运算都得到了相同的索引值02,在02的索引上对应着Rose的value:lo,所以只能向下线性查找一个空桶放置Jack的value值tr,这样避免了都在02这一行数据里存放多个value值。
在这里插入图片描述
(2)平方探测:也是向下找空桶,只不过以平方来找,比如第一次在03索引处(1^2)第二次就在07处(2^2),第三次在016索引处(3^3),直到遇到空桶放置value数据。

2.再哈希法:设计多个哈希函数
比如将Jack的key放到另一个哈希函数中计算哈希值得到不相同的索引值,来存放数据。
在这里插入图片描述
3.链地址法(JDK 1.8之后采用的):通过链表将同一索引index的元素串起来。这个Mysql中的引擎Memory就是用哈希索引来存储
在这里插入图片描述

3.JDK1.8的哈希冲突解决方案

单链表排建立在哈希值相同的情况下,不同直接按照数组一对一存放value数据了。
1.8后采用了上述链地址法:
1.当相同key或者不同key通过哈希算法得出相同的索引值(01)时,把相同的索引值对应的所有value按照单链表来排好。

2.记住key值也被存储到链表里,因为有相同的哈希值hashcode,通过与数组长度-1&位运算后,索引值也相等,需要调用equals方法,来查看key值对应着的是链表中的哪一个key,如果key唯一则直接添加数据到链表后面,如果key重复则把新传进来的key的value覆盖到原先key的value处。

在这里插入图片描述
本题中哈希表的索引数组容量正好是64,单链表节点数只有40、50、60三个,不满足节点数量大于8,就不需要转成红黑树。
解析hashcode和equals方法:key -value ("a",40);("b",45);("c",60);("b",50),它们的key通过哈希函数计算都是相同的索引值01,所以value数据可以按照单链表存储。原先单链表存储的是40-45-60,当读到相同的key是b,通过hashcode计算发现哈希值也相同,则哈希值与(桶数组容量-1)进行&位运算得出的索引值也相同,索引值存放在桶数组中,这时调用equals方法,看相同的索引值(01)中,链表中存放的key和传进来的key是否相同,如果key相同,则把value数据覆盖(50覆盖45),不同则添加到链表最后。
在这里插入图片描述

4. 哈希函数

发现table.length是数组的容量,一个数组设立则大小就固定了,所以哈希值相同hash_code(key),则和数组大小进行运算时,得出的索引值也相同

在这里插入图片描述
哈希值计算:一般不相等的key,我们要保证他们的哈希值不同,这样就不会有哈希冲突,那么就是一个索引对应一个value数据
哈希算法就是O(1)级别。
在这里插入图片描述

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值