使用哈希值和&和2^n数组生成索引值的原理

用&代替%的原因是&计算速度快

先看这一段代码

public int hash(Object key){
     return hash_code(key)&(table.length-1);//table.lenth的长度需要是2^n          
}

首先这个hash_code的方法是根据一个key值获取到一个哈希值,之后与后面的数进行与运算,对于不同的hash值,映射到对应的索引上

(table是一个数组,它的索引值也为table.length-1)

1.首先解释为什么table.length需要是2^n

因为2^n的数的二进制表示有一个特点,那就是1开头,后面全是0,比如8是1000,16是10000,以此类推
那么2^n-1的数的二进制表示有什么特点的,那就是0开头,后面全是1,比如7是0111,15是01111

2.根据这个特点我们回到方法体本身,进行一个例子的计算

假设有一个长度为16的数组,那么我怎么通过hash算法把不同的key值算出来的hash值映射到索引上去呢。
假设其中某个key值的hash值的二进制表示为1101010011010,共13位
16-1的二进制为01111
进行&运算,位数上都为1才取1,其余取0
1101010011010
0000000001111
------------------
0000000001010
可以发现在01111之前的位数进行&运算出来都是0,那么有个问题,该计算结果1010的十进制值是10,那么请问&运算后最终的结果存不存在一个取值范围
答案是存在,如果最终的计算结果为01111,那么就是&运算的最大值为15,如果最终的结果为00000,那么就是&运算的最小值为0
这样一来,该&运算的取值范围只由后面这个2^n-1决定,又因为2^n-1又是该数组的索引的最大值,该数组索引的最小值也是0
所以,任何哈希值进行&运算后都会映射到这个数组对应的索引上

3.这就是根据hash值来定位索引的方式,当然会产生hash冲突,就是有多个哈希值经过&运算后的结果是一样的,这个就要通过链表来解决了,这个先按下不表

 

posted @ 2020-11-12 21:51  人菜话多帅瓜皮  阅读(273)  评论(0编辑  收藏  举报