什么是hash?
hash又称为散列,就是把一串任意长度的输入通过hash算法转换为固定长度的输出串,这个串就叫做hash值。比如Java集合中的map,根据key来计算hash值code,code = hash(key)。
hash函数,算法
- MD4:基于32位的位操作实现的
- MD5:比md4更复杂一些,因此速度更慢一些,安全性更好
- SHA-1:对小于264位的输入,产生160位的散列值
hash表
hash表称为散列表,是通过key-value访问的数据结构。通过把key计算出的hash值映射到表中的一个位置,然后读取该位置的数据,提高访问效率。函数称为散列函数,存放记录的数组称为散列表。
- 如果两个哈希值不同,那么两个散列值的输入肯定不同
- 如果不同的输入得到相同的输入,就称为hash碰撞
- 抗篡改能力:一个数据块改变一个比特位,其hash值的改动也比较大
- hash是一种单向函数的非对称的,只有从明文到密文的过程,不可逆。
什么是hash冲突?
在一般的情况下,不同的输入在经过hash运算,得到相同的hash值的情况及其少见(但是并不代表不存在这种情况),如果在数据量非常大的情况下,不同输入产生了相同的hash值,就是我们所说的hash冲突,也叫作hash碰撞。
如何解决hash冲突
- 开放地址法
当计算一个key的hash值时,p=hash(key)出现冲突后,以p为基础再次计算出一个hash地址,如果还有冲突,再继续计算下去,直到得到一个没有冲突的hash值。主要有三种方式:
线性探测再散列:每次计算时都从p的基础上+1,2,3,4,5…n;
二次探测再散列:每次计算在p的基础上+1的平方,-1的平方,+2的平方,-2的平方…
伪随机数探测再散列:利用随机数生成器获取一串随机数,2,5,6,8…,每次计算按随机数加。
- 链地址法(拉链法):
把hash值一致的数据放在同一个链表里,称为一个桶,map就是采用这个方法消除hash冲突的
- 再hash
采用多个hash函数,这种方法是同时构造多个不同的哈希函数:
Hi=RH1(key) i=1,2,…,k
当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。
- 建立公共溢出区:
将hash表分为溢出表和基本表,和基本表发生冲突的数据放入溢出表。