集合6、集合_Map接口_HashMap底层原理及源码分析
★HashMap的底层原理及源码分析
一、底层原理
jdk7:
HashMap map = new HashMap();
在实例化以后,底层创建了长度是16的一维数组Entry[] table
...可能已经执行过多次put...
map.put(key1, value1);
首先,调用key1所在类的hashCode()计算key1的哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
如果,此位置上的数据为空,此时key1-value1添加成功 ------情况1
如果,此位置上的数据不为空(意味着此位置上存在一个或多个(以链表形式存在)数据),比较key1和已经存在的一个 或多个数据的哈希值:
如果key1的哈希值与已经存在的数据的哈希值不同,此时key1-value1添加成功 ------情况2
如果key1的哈希值和已经存在的某一个数据的哈希值相同,继续比较:调用key1所在类的equals()方法
如果equals()返回false:此时key1-value1添加成功 ------情况3
如果equals()返回true:使用value1替换value2
补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储
在不断的添加过程中,会涉及到扩容问题,当超出临界值且要存放的位置非空时,默认的扩容方式:扩容为原来的2倍,并将原来的数据复制过来
jdk8(相较于jdk7的不同):
-
new HashMap(); 底层没有创建一个长度为16的数组
-
jdk 8底层的数组是:Node[],而非Entry[]
-
首次调用put()方法时,底层创建长度为16的数组
-
jdk 7底层结构只有:数组+链表;jdk 8底层结构:数组+链表+红黑树。
当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组的长度>64时,此时此索引位置上的所有数据改为使用红黑树存储。
二、源码分析
DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
MAXIMUM_CAPACITY : HashMap的最大支持容量,2^30
DEFAULT_LOAD_FACTOR :HashMap的默认加载因子
TREEIFY_THRESHOLD :Bucket中链表长度大于该默认值,转化为红黑树
UNTREEIFY_THRESHOLD :Bucket中红黑树存储的Node小于该默认值,转化为链表
MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量。(当桶中Node的 数量大到需要变红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY时,此时应执行 resize扩容操作这个MIN_TREEIFY_CAPACITY的值至少是TREEIFY_THRESHOLD的4 倍。)
table:存储元素的数组,总是2的n次幂
entrySet:存储具体元素的集
size :HashMap中存储的键值对的数量
modCount :HashMap扩容和结构改变的次数
threshold:扩容的临界值 = 容量 * 填充因子:16 * 12 = 0.75
loadFactor:填充因子:12

浙公网安备 33010602011771号