table:Node类型的键值对。存储数据
entrySet:Set类型的参数
size:int类型,表示hashMap的大小
modCount:int类型,fail-fast标识
threshold:int类型,阈值,当hashMap的实际容量大于阈值时,要进行扩容。
loadFactor:float类型,加载因子
实际存储数据的为Node
hash:int类型,表示当前Node
key:K类型,表示当前键值对的key值
value:表示key对应的value值
next:Node
Node(int hash, K key, V value, Node
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
初始化加载因子为默认的加载因子0.75。不初始化table,添加第一个数据时才初始化table
自定义初始化容量和加载因子,一般不建议手动给加载因子。
自定义初始化容量,加载因子取默认的。
此处的hash值为key.hashCode^(key.hashCode >>> 16)
计算index的方式为hash&(capacity-1)
1.4.1.1、HashMap中没存值时:
①判断table是否为null或者table的length是否为0,
②为null或者0则调用resize()初始化table
③根据key值得hash值算出index,并判断下标为index的值是否为null
④为null则调用newNode()方法创建一个新的Node存入index处
⑤fail-fast标志modCount加1 ,table长度加1并与阈值threshold比较
⑥长度大于阈值,调用resize()方法进行扩容
1.4.1.2、HashMap有值时:
①对比key值的hash与index下标处的Node的hash值,以及key值是否相等,若相等,将oldValue替换为newValue并返回oldValue
②判断key值hash对应的index处的Node是否为TreeNode(红黑树的节点),若为,调用TreeNode.putTreeVal()处理
③循环获取链表中最后一个节点p,并将需要新增的数据添加到p的next,即成为新的最后一个节点:同时判断链表长度是否超过8,若超过,则将调用treeifyBin()方法将链表结构转化为红黑树结构。
若当前table的存储size小于64时,不进行红黑树化,而进行扩容。
1.4.2.1、初始化HashMap的table
此时oldCap以及oldThr都是0,会直接设置newCap为16,threshold为16*0.75,即12。然后new一个大小为newCap的Node类型的数组返回
1.4.2.2、HashMap进行扩容时
①设置好新的Capacity、threshold、
1>当oldCapacity>0时
若oldCap>=规定的Capacity时,将threshold设置为Integer.MAX_VALUE并返回旧的table,因为此时table扩容已达到上限
否则将newCap扩容为oldCap的2倍,newThr变为oldThr的2倍
2>当oldThr>0时,将newCap也设为一样大
②分情况重新将旧table中的数据存储到新的table中
当前index只存了一个的、当前index存的是TreeNode类型的、存的是链表类型的
1.4.2.2.1、旧table中当前index只存了一个值
重新计算key值在新table中的index,将旧键值对赋值给新table的index处。
1.4.2.2.2、存储的是TreeNode类型
调用TreeNode.split方法。
1.4.2.2.3、存储的是链表类型的。
循环链表,计算新下标。
计算规则,将旧hash值与旧table长度做&运算,若为0,则新的index值与旧的index值相等;否则新的index为旧的index+oldCap。