Node<k,v>[] table:HashMap底层存储数组
Float loadfactor :加载因子,无参初始化时为默认加载因子
Int threshold:扩容阈值,一般为table数组的长度*加载因子(0.75)
Int Size:集合的长度(kv键值对的个数)
final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 默认数组长度16
final int MAXIMUM_CAPACITY = 1 << 30;最大数组长度
final float DEFAULT_LOAD_FACTOR = 0.75f;默认加载因子
final int TREEIFY_THRESHOLD = 8;转树形时链表的最小长度
final int MIN_TREEIFY_CAPACITY = 64;转树形时table数组的最小长度
无参构造初始化: 通过此构造方法,将加载因子初始化为默认加载因子(0.75f),数组长度和扩容阈值未初始化,此时均为0.
单参构造初始化:通过此构造方法,给定了数组的长度,并调用双参的构造方法,对成员变量进行初始化
双参构造初始化:通过此构造方法传入的两个参数,对数组长度和加载因子及扩容阈值同时进行了初始化。
首先通过扰动函数计算所存放元素中key的hash值:
其次在添加元素前判断之前的数组table是否为空,如果是,则进行扩容
其次通过(table数组长度-1)%hash的方法,确定要添加元素所存放的位置,并判断此位置是否已有元素,如果没有则可直接存放
如果此位置已经有元素,通过hash和equals判断要添加元素的key值和已经在此位置元素的key值是否相同,如果key值不同,则对原位置元素的value进行覆盖
如果key值相同,则说明此时发生了hash冲突,此时将要添加的元素以node节点的形式连到原位置元素的后面,先判断是否为树形节点,如果不是则按单向链表的形式进行连接
后续添加元素,如果仍然在此位置发生哈希冲突,就继续往链表最后添加的元素后面连接,用p.next==null判断,在此过程中重复上面的过程,即判断后续添加的元素与前面的元素的key值是否相同,相同则覆盖原元素的value,不相同则继续进行连接
如果同一个位置的连接的元素超过8个(链表长度大于8),同时table数组的长度小于64,则需进行扩容,当同一个位置的连接的元素超过8个同时数组长度超过64,则改为红黑树的形式连接要添加的元素
还有一种情况也需要扩容,即数组中的元素个数大于扩容阈值,此时会进行扩容
HashMap集合添加元素时共有三种情况下会扩容:
首先是首次添加元素,此时扩容机制为,数组长度从0扩容为16,扩容阈值从0扩容为12
其次是同一个位置的连接的元素超过8个(链表长度大于8),同时table数组的长度小于64,则需进行扩容,此时扩容机制是数组长度和扩容阈值都扩容为原来的2倍
另外·当数组中元素超过其扩容阈值时,也会进行扩容,此时扩容机制和上一步的相同(数组长度和扩容阈值按之前的两倍扩容)
因篇幅问题不能全部显示,请点此查看更多更全内容