集合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的不同):

  1. new HashMap(); 底层没有创建一个长度为16的数组

  2. jdk 8底层的数组是:Node[],而非Entry[]

  3. 首次调用put()方法时,底层创建长度为16的数组

  4. 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

posted @ 2021-11-19 23:47  叁玖贰拾柒  阅读(9)  评论(0)    收藏  举报