hash 算法

本文详细介绍了哈希表的基本概念及其在Java中HashMap的具体实现原理。包括哈希算法、散列函数的作用、如何处理哈希冲突等问题,并深入探讨了HashMap如何通过内部类Entry和链表结构来存储数据。

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

比较详细的:http://blog.youkuaiyun.com/zxycode007/article/details/6999984

hash算法 (hashmap 实现原理):http://zha-zi.iteye.com/blog/1124484

Hash ,一般翻译做“ 散列” ,也有直接音译为“ 哈希” 的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不 同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

HASH 主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128 位的编码, 这些编码值叫做HASH 值. 也可以说,hash 就是找到一种数据内容和数据存放地址之间的映射关系

例如字符串 hello 的哈希算法

char* value = "hello"; int key = (((((((27* (int)'h'+27)* (int)'e') + 27)  * (int)'l') + 27) * (int)'l' +27) * 27 ) + (int)'o' ;。

 

  数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易 的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法—— 拉链法,我们可以理解为“ 链表 的数组” ,如图:


 

 

 

HashMap其实也是一个线性的数组实现的,所以可以理解为其存储数据的容器就是一个线性数组。这可能让我们很不解,一个线性的数组怎么实现按键值对来存取数据呢?这里HashMap有做一些处理。

 

    1.首先HashMap里面实现一个静态内部类Entry 其重要的属性有 key , value, next,从属性key,value我们就能很明显的看出来Entry就是HashMap键值对实现的一个基础bean,我们上面说到HashMap的基 础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存在Entry[]里面。

     2.既然是线性数组,为什么能随机存取?这里HashMap用了一个小算法,大致是这样实现:

 

Java代码   收藏代码
  1. 存储时:  
  2.   
  3. int hash = key.hashCode();--> 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值  
  4.   
  5. int index = hash % Entry[].length;  
  6.   
  7. Entry[index] = value;  
  8.   
  9. 取值时:  
  10.   
  11. int hash = key.hashCode();  
  12.   
  13. int index = hash % Entry[].length;  
  14.   
  15. return Entry[index]  

 

到这里我们轻松的理解了HashMap通过键值对实现存取的基本原理

    3.疑问:如果两个key通过hash % Entry[].length得到的index相同,会不会有覆盖的危险?

这里HashMap里面用到链式数据结构的一个概念.上面我们提到过Entry类里面有一个next属性,作用是指向下一个Entry。打个比方, 第一个键值对A进来,通过计算其key的hash得到的index=0,记做:Entry[0] = A.一会后又进来一个键值对B,通过计算其index也等于0,现在怎么办?HashMap会这样做:B.next = A,Entry[0] = B,如果又进来C,index也等于0,那么C.next = B,Entry[0] = C;这样我们发现index=0的地方其实存取了A,B,C三个键值对,他们通过next这个属性链接在一起。所以疑问不用担心。

到这里为止,HashMap的大致实现,我们应该已经清楚了。

当然HashMap里面也包含一些优化方面的实现,这里也啰嗦一下。

比如:Entry[]的长度一定后,随着map里面数据的越来越长,这样同一个index的链就会很长,会不会影响性能?

HashMap里面设置一个因素(也称为因子),随着map的size越来越大,Entry[]会以一定的规则加长长度。

 

 

解决hash冲突的办法

1)开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)

2)再哈希法

3)链地址法

4)建立一 公共溢出区

 

java 中hashmap的解决办法就是采用的链地址法

 

<think>嗯,用户问的是关于哈希算法的问题。我需要先解释哈希算法是什么,以及它在Python中的应用。首先,哈希算法的作用是将任意长度的数据转换成固定长度的哈希值,这个值通常用来快速查找、数据完整性校验等。常见的应用场景比如哈希表、加密、校验文件等。 接下来,我得列举常见的哈希算法,比如MD5、SHA系列,还有Python中的内置hash()函数。需要提到它们的区别,比如MD5虽然快但不够安全,SHA-256更安全但速度慢一些。另外,Python的hash()函数可能在不同环境下有不同的表现,比如在64位和32位系统上结果不同,或者因为哈希随机化导致不同进程的结果不同。 然后,我需要给出Python中使用这些算法的代码示例。比如用hashlib库实现MD5、SHA-256,以及如何用hash()函数处理不可变类型。还要注意,可变类型如列表不能直接哈希,但元组可以。所以可能需要转换类型后再使用hash()。 另外,可能需要提到哈希算法的特性,比如确定性、抗碰撞性、雪崩效应等。这些是哈希算法设计的重要原则,确保其安全性和有效性。 在问题解决方面,用户可能遇到哈希冲突的问题,这时候需要解决方法,比如链地址法或开放寻址法。或者在使用哈希函数时需要注意安全性,避免使用不安全的算法如MD5存储密码,应该用bcrypt或PBKDF2等。 最后,相关的问题应该围绕哈希算法的应用场景、解决冲突的方法、安全性和Python中的具体实现。确保问题覆盖用户可能进一步询问的方向。</think><< 哈希算法Hash Algorithm)是一种将任意长度的输入数据转换为固定长度输出的算法。输出的结果称为哈希值(Hash Value)或摘要(Digest)。哈希算法具有以下核心特性: 1. **确定性**:相同输入始终产生相同哈希值。 2. **高效性**:计算速度快。 3. **抗碰撞性**:不同输入极难生成相同哈希值。 4. **不可逆性**:无法从哈希值反推原始输入。 ### Python中的哈希算法实现 Python通过标准库`hashlib`提供了多种哈希算法。以下是常见算法和代码示例: #### 1. MD5(不推荐用于安全场景) ```python import hashlib data = "Hello, World!".encode('utf-8') md5_hash = hashlib.md5(data).hexdigest() print(md5_hash) # 输出: 65a8e27d8879283831b664bd8b7f0ad4 ``` #### 2. SHA-256(安全哈希算法) ```python sha256_hash = hashlib.sha256(data).hexdigest() print(sha256_hash) # 输出: dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f ``` #### 3. Python内置`hash()`函数 ```python # 仅适用于不可变对象(如整数、字符串、元组) print(hash("Python")) # 输出: 539294692(Python 3.11+可能启用随机哈希种子) ``` ### 哈希算法应用场景 1. **数据完整性验证**(如文件校验) 2. **密码存储**(需结合盐值) 3. **哈希表数据结构**(字典实现基础) 4. **数字签名** ### 注意事项 - **碰撞风险**:MD5/SHA-1已知存在碰撞漏洞 - **哈希长度**:SHA-256输出256位,SHA-512输出512位 - **加盐处理**:存储密码时应使用`hashlib.pbkdf2_hmac` ### 哈希冲突示例 ```python # 不同输入可能产生相同哈希值(概率极低但存在) collision1 = hash("a") # 不同Python版本结果可能不同 collision2 = hash("b") print(collision1 == collision2) # 可能输出False,但理论上存在True的情况 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值