HashMap系列 (1)

先看下hash(Object key)方法,详细大家基本都能看懂,但是知道这一步(h = key.hashCode()) ^ (h >>> 16)原因的人很少。

 static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
 }

这里主要理解一下 (h = key.hashCode()) ^ (h >>> 16) 这一段代码

hash 算法的精髓都在这里面

1.key.hashCode() 获取hash 值,为什么不用hashCode直接比较呢?

答: 这里就要说一下HashMap 默认为什么是16位 ,hashCode 是int 类型的, int 类型是16位的. 
而为什么不用hashCode 直接比较,是因为hashCode 16位,而16位的数字散列的肯定不如32位的二进制散列的均匀,更容易发生hash碰撞所以不用hashCode直接比较

2.从代码中我们可以明显的知道高于16位的通过 ^ (异或) 右移16位来得到比较的值,但是小于16位的呢?

答: 简单的从上面代码可以得知, 如果是大于16位得到hashCode,然后右移16位,其实比较的也就是从左往右的16位数字. 当时我就有个困惑 小于16位呢?(这也是自己对^异或运算掌握的不够好)其实异或后得到的还是它本身

PS: 下面是对我自己的解释: 

异或运算符(^)
参加运算的两个数据,按二进制位进行“异或”运算。
运算规则:0^0=0;  0^1=1;  1^0=1;   1^1=0;
即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。

首先右边运算得到的是32位全为0, 右边是本身,而 1^0=1;的情况还是1 所以得到的结果还是它本身

3.为什么加载因子是0.75呢?

答: 其实是通过泊松分布来计算的.在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少扩容rehash操作次数,所以,一般在使用HashMap时建议根据预估值设置初始容量,以便减少扩容操作。

选择0.75作为默认的加载因子,完全是时间和空间成本上寻求的一种折衷选择。

在维基百科中的解释是这样的:

对于开放定址法,加载因子是特别重要因素,应严格限制在0.7-0.8以下。超过0.8,查表时的CPU缓存不命中(cache missing)按照指数曲线上升。因此,一些采用开放定址法的hash库,如Java的系统库限制了加载因子为0.75,超过此值将resize散列表。

你可能感兴趣的:(HashMap系列 (1))