【Java】哈希冲突(哈希碰撞)

本文介绍了哈希冲突的原因及如何处理。哈希冲突是由于不同关键字具有相同哈希地址而产生的。尽管无法完全避免,但可以采取开放地址法、再哈希地址法、链地址法和建立公共溢出区等方法来解决。其中,开放地址法包括线性探测、二次探测和伪随机探测;链地址法通过链表将相同哈希地址的关键字链接在一起。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


为什么发生哈希冲突(哈希碰撞)

  当向hash表中存放数据时,会使用hash函数计算出对应的hash函数值,即哈希地址,所以会出现不同关键字具有相同hash函数值,即不同数据具有同一hash地址的情况,这个时候就发生了哈希冲突。

能否完全避免哈希冲突

  虽然可以选择不同的哈希函数去避免冲突的产生,但是数据量增长,始终会产生哈希冲突,因此只能尽量减少。

常用处理哈希冲突的方法

  1. 开放地址法
  2. 再哈希地址法
  3. 链地址法
  4. 建立公共溢出区

1.开放地址法

  当产生哈希冲突时,就在哈希表中寻找另一个空的位置存放关键字。如何寻找另一个空的位置,也有不同的规则。

  1. 线性探测再散列
  2. 二次探测再散列
  3. 伪随机探测再散列

1.1线性探测再散列

  当发生哈希冲突时,即某一位置已放了关键字,会查询下一个位置上是否是空的,空的便放入,否则再下一个位置尝试放入直到解决冲突。每次查询下一个未冲突的位置的增量d为1、2、3、4…(不断自增),即不断加上增量d,从而寻找下一个空的位置。
例如:
  关键字(35、74、02、31、39、98、99、100)按哈希函数H(key) = key / 7 和开放地址法中的线性探测处理哈希冲突

  1. 35关键字放在0位置
0 1 2 3 4 5 6 7 8 9
35
  1. 74关键字放在4位置
0 1 2 3 4 5 6 7 8 9
35 74
    ### Java哈希冲突的概念 在Java中,哈希冲突指的是当两个不同的对象通过相同的哈希函数计算得到相同的位置索引时发生的情况。这种现象也被称为碰撞哈希碰撞),意味着这些对象将会被映射到哈希表中的同一位置[^3]。 ### 哈希冲突的原因 哈希冲突产生的根本原因是有限大小的哈希表无法容纳无限数量的对象键值对。即使使用精心设计的哈希算法来分配存储空间,由于数据量庞大或者特定模式的数据分布,仍然不可避免地会出现多个不同对象拥有相同哈希码的情形。此外,在某些情况下,即使是高质量的哈希函数也可能因为输入数据特性而表现出较差性能,从而增加冲突概率[^2]。 ### 解决方案 #### 链地址法 (Separate Chaining) 链地址法是一种常用且有效的处理哈希冲突的方法之一。在这种策略下,每一个桶位实际上是一个容器结构(通常是列表或树形结构),能够保存多条记录。每当新加入一条记录发现目标槽位已被占用,则将其附加至该槽位对应的集合之中;查找操作同样遵循此逻辑遍历相应链接节点直至找到匹配项为止。 #### 开放定址法 (Open Addressing) 开放定址法则是在探测过程中一旦检测到当前欲插入位置已有其他元素存在时,并不会立即停止而是继续按照某种探查序列寻找下一个可用空闲单元格完成放置过程。具体实现方式有线性探测(linear probing),二次探测(quadratic probing)以及双重散列(double hashing)[^1]: - **线性探测**:最简单的形式是每次遇到已占满情况便向后移动固定步长直到遇见未使用的槽位; - **二次探测**:改进版线性探测,采用平方增量而非常数间隔前进; - **双重散列**:利用第二个辅助性的hash function决定跳跃距离,有助于进一步打乱访问路径降低局部聚集效应的影响程度。 ```java // 示例代码展示如何自定义hashCode()方法以减小冲突几率 @Override public int hashCode(){ final int prime = 31; int result = 17; // 初始值选取一个小素数 result = prime * result + ((name == null)?0:name.hashCode()); result = prime * result + age; return result; } ```
    评论 1
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值