在同一个版本的Jdk中,HashMap、HashTable以及ConcurrentHashMap里面的hash方法的实现是不同的
HashMap采用的是位运算:
当哈希表的大小为素数时,简单的取模哈希的结果会更加均匀,所以单从这一点上看,HashTable的哈希表大小选择,似乎更高明些。因为hash结果越分散效果越好。
HashTable采用的是直接取模:
在取模计算时,如果模数是2的幂,那么我们可以直接使用位运算来得到结果,效率要大大高于做除法。所以从hash计算的效率上,又是HashMap更胜一筹
但是,HashMap为了提高效率使用位运算代替哈希,这又引入了哈希分布不均匀的问题,所以HashMap为解决这问题,又对hash算法做了一些改进,进行了扰动计算。
常见的Hash函数
直接定址法
直接以关键字k或者k加上某个常数(k+c)作为哈希地址
数字分析法
提取关键字中取值比较均匀的数字作为哈希地址
除留余数法
用关键字k除以某个不大于哈希表长度m的数p,将所得余数作为哈希表地址
分段叠加法
按照哈希表地址位数将关键字分成位数相等的几部分,其中最后一部分可以比较短。然后将这几部分相加,舍弃最高进位后的结果就是该关键字的哈希地址
平方取中法
如果关键字各个部分分布都不均匀的话,可以先求出它的平方值,然后按照需求取中间的几位作为哈希地址
伪随机数法
采用一个伪随机数当作哈希函数
哈希碰撞(hash冲突)
冲突处理分为以下四种方式:
1:开放地址
线性探测再散列 :即依次向后查找
二次探测再散列:即依次向前后查找,增量为1、2、3的二次方
伪随机探测再散列:随机产生一个增量位移
2:再哈希
出现冲突后采用其他的哈希函数计算,直到不再冲突为止
3:链地址
在出现冲突的地方存储一个链表,所有的同义词记录都存在其中。形象点说就行像是在出现冲突的地方直接把后 续的值摞上去
4:建立公共溢出区
将哈希表分为基本表和溢出表两部分,发生冲突的元素都放入溢出表中。