如何解决hash冲突



hash冲突

在使用hash表时肯定会遇到hash冲突的情况(看你设计的hashCode如何,设计的好,冲突就少一些)

但是冲突再少也会存在冲突,那就需要有处理冲突的方法,下面列出来一些处理hash冲突的方法

开放定址法

一旦发生冲突,就去寻找下一个空的散列地址,只要散列表足够大,总能找到空位

线性探测法

f(key) = (f(key)+di) mod m (di=1,2,3,…,m-1)

这种每次加一向后遍历查找空位的方式是线性探测法,但是这样对于存入和查找的效率都会很低

二次探测法

基于线性探测法进行改进,使得其可以双向探测,di=12,22,32…q2(q<=m/2),使用平方运算来使的不让关键字都聚集在某一区域

再散列法

使用不同的散列函数来进行散列,一个冲突则使用另一个,不过这样做也增加了计算的时间

链地址法

将所有冲突的记录存储在一个单链表中,只是这样在查找时需要遍历单链表

公共溢出法

对于冲突的数据,都存放到另一个溢出表中,在查找时,先在散列表中进行查找,如果没有则去溢出表中顺序查找

参考文献

HashMap主要通过**链表法**和**红黑树优化**来解决Hash冲突,具体过程如下: 1. **链表法**:当多个键值对映射到同一个桶(即发生Hash冲突)时,HashMap会将这些键值对以链表的形式存储在同一个桶中。每个桶中的第一个元素是一个`Node`对象,后续冲突的元素会通过`next`指针依次连接,形成链表结构。 2. **红黑树优化**:当链表的长度超过阈值(默认为8)时,HashMap会将链表转换为红黑树。红黑树是一种自平衡的二叉查找树,能够保证在最坏情况下,查找、插入和删除操作的时间复杂度为O(log n),从而提高HashMap的性能。 3. **扩容与再哈希**:当HashMap中的元素数量超过负载因子(默认为0.75)与容量的乘积时,HashMap会进行扩容操作。扩容后,所有元素会重新计算哈希值,并分配到新的桶中,从而减少冲突的可能性。 ```java // 伪代码示意HashMap的put操作(简化版) public V put(K key, V value) { // 计算key的哈希值,并定位到桶的位置 int hash = hash(key); int index = hash & (table.length - 1); // 检查桶中是否已有元素 if (table[index] == null) { // 桶为空,直接插入新节点 table[index] = new Node<>(key, value, null); } else { // 桶不为空,遍历链表或树 Node<K,V> e; if (table[index] instanceof TreeNode) { // 如果是红黑树,调用树的插入方法 e = ((TreeNode<K,V>)table[index]).putTreeVal(this, key, value); } else { // 如果是链表,遍历链表 for (e = table[index]; e != null; e = e.next) { // 如果找到相同的key,更新value if (e.key.equals(key)) { V oldValue = e.value; e.value = value; return oldValue; } } // 遍历完链表未找到相同key,将新节点添加到链表末尾 Node<K,V> newNode = new Node<>(key, value, table[index]); table[index] = newNode; // 检查链表长度是否超过阈值,如果是则转换为红黑树 if (链表长度 > 8) { treeifyBin(table, index); } } } // 如果插入新节点后元素数量超过阈值,进行扩容 if (++size > threshold) { resize(); } return null; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾光师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值