
Hashmap源码阅读笔记
2021-03-05 / highPhone啊
JDK源码版本: Oracle JDK1.8.0_271
常量
1 | //默认的初始化容量 |
成员变量
1 | /* ---------------- Fields -------------- */ |
静态方法hash()和tableSizeFor()
hash()
1
2
3
4static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//高16位右移后与原值做异或计算
}这个函数也叫扰动函数,在理解扰动函数前,我们要先知道在HashMap中,根据元素hashcode计算数组下标的方法是
(n-1) & hash,若果没有扰动函数重新计算key的hash值,那么,对于初始容量16来说,n-1的值为15,基于(n-1) & hash算出来的下标,只与hash值的最后4位有关,前28无论是何值,都不影响计算出来的下标,这样,发生hash碰撞的机率会比较高。扰动函数的作用就是让hash高16位与低16位的值做一个异或,让所有数值的特征结合到一起,尽量使hash值中每一位数值对下标的计算都有意义,降低hash碰撞tableSizeFor()
1
2
3
4
5
6
7
8
9static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}这个方法是为了保证hash数组的长度一定是2的n次方,且返回的值是大于输入参数且最小的2的整数次幂的数, 我们用输入值9来做一个计算,就能很清楚的看到计算规则了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14cap 0000 0000 0000 0000 0000 0000 0000 1001
n = cap - 1 0000 0000 0000 0000 0000 0000 0000 1000
n >>> 1 0000 0000 0000 0000 0000 0000 0000 0100
-----------------------------------------------------------------
n |= n >>>1 0000 0000 0000 0000 0000 0000 0000 1100
n >>> 2 0000 0000 0000 0000 0000 0000 0000 0011
-----------------------------------------------------------------
n |= n >>>2 0000 0000 0000 0000 0000 0000 0000 1111
.......
n >>> 16 0000 0000 0000 0000 0000 0000 0000 0000
-----------------------------------------------------------------
n |= n >>>16 0000 0000 0000 0000 0000 0000 0000 1111上述计算中,有一步
n = cap - 1操作,这一步是为了防止输入的cap刚好是2的整数次幂,如果不减1,计算结果最终会是预期值的2倍,同时,由于int只有32位,做到n |= n >>> 16这一步时,已经可以确保32位全是1,这时计算结果为MAXIMUM_CAPACITY
添加元素putVal()
此方法是往HashMap中添加元素的核心实现
1 | final V putVal(int hash, K key, V value, boolean onlyIfAbsent, |
扩容机制resize()
1 | final Node<K,V>[] resize() { |
本文链接:https://highphone.xyz/b2b5308.html