取模运算与java的hashmap实战

why:

  对于取模运算,大家最熟悉的是:N=M%L。但是在java的jdk库中经常见到:N=M&L。这二者有什么异同,使用有什么场景要求,以及&为何能代替%?在java的hashmap中具体是怎么使用的?

 

what:

  当L=2的n次幂时,M%L == M&L。长度L为2的n次幂时,模运算 % 可以变换为按位与 & 运算。

 

  前提知识:

    ①、"<<" 左移:右边空出的位上补0,左边的位将从字头挤掉,左移一位其值相当于乘2。

    ②、">>"右移:右边的位被挤掉,右移一位其值相当于除以2。对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或补1,这取决于所用的计算机系统。

    ③、">>>"无符号右移,右边的位被挤掉,对于左边移出的空位一概补上0。

 

  证明:

    根据二进制数的特点,对于给定一个任意的十进制数,是可以将其用二进制的表示方法分解的:

      XnXn-1Xn-2....X1X0     =   Xn*2n+Xn-1*2n-1+......+X1*21+X0*20                       3-1公式

    

    对于除法,“被除数”是满足分配率的(除数不满足):

      成立:(a+b)÷ c = a÷c + b÷c                                                                          3-2公式

    

    通过 3-1公式以及 3-2 公式,我们可以得出当任意一个十进制除以一个2k(2的K次幂)的数时,我们可以将这个十进制转换成3-1公式的表示形式:

      (XnXn-1Xn-2....X1X0)  / 2k   =  (Xn*2n+Xn-1*2n-1+......+X1*21+X0*20) / 2k = Xn*2n /  2k +Xn-1*2n-1 /  2k  +......+  X1*21 /  2k + X0*20 /  2k

    如果我们想求上面公式的余数,相信大家一眼就能看出来:      

      ①、当 0<= k <= n 时,余数为 Xk*2k+Xk-1*2k-1+......+X1*21+X0*20   ,也就是说 比 k 大的 n次幂,我们都舍掉了(大的都能整除 2k),比k小的我们都留下来了(小的不能整除2k)。那么留来下来即为余数

      ②、当 k > n 时,余数即为整个十进制数。

    重要的结论

      一个十进制数对一个2n 的数取余,我们可以将这个十进制转换为二进制数,将这个二进制数右移n位移掉的这 n 位数即是余数


    如何获取这移掉的 n 为数

      例子:20,21,22....2n  用二进制表示如下:

        0001,0010,0100,1000,10000......

      我们把上面的数字减一:

        0000,0001,0011,0111,01111......

      根据与运算符&的规律,当位上都是 1 时,结果才是 1,否则为 0。所以任意一个二进制数对 2k 取余时,我们可以将这个二进制数与(2k-1)进行按位与运算,保留的即使余数。

  

  这就完美的证明了前面给出的结论

    当 lenth = 2n 时,X % length = X & (length - 1);

 

how(java中hashmap如何使用):

  1、初始容量为 1<<4,即容量为16:

 

 

   2、负载因子是0.75,当存入HashMap的元素占比超过整个容量的75%时,进行扩容,而且在不超过int类型的范围时,进行2次幂的扩展(指长度扩为原来2倍)

 

 

 

 

 

   3、新添加一个元素时:

    取 hashCode 值: key.hashCode();高位参与运算:h>>>16(抗扰动);取模运算:(n-1) & hash

 

    对于第二步将取得的哈希值无符号右移16位,高位补0。并与前面第一步获得的hash码进行按位异或^ 运算。这样做有什么用呢?

      这其实也是扰动函数,为了降低哈希码的冲突。右位移16位,正好是32bit的一半,高半区和低半区做异或,就是为了混合原始哈希码的高位和低位,以此来加大低位的随机性。而且混合后的低位掺杂高位的部分特征,这样高位的信息也被变相保留下来。也就是保证考虑到高低Bit位都参与到Hash的计算中。

 

 

  增加扰动有何好处?

    当然这个结果也是有人做过实验证明的:

 

 

posted @ 2022-06-14 14:37  修心而结网  阅读(382)  评论(0编辑  收藏  举报