美文网首页
HashMap达到扩容阀值也不一定就开始进行扩容

HashMap达到扩容阀值也不一定就开始进行扩容

作者: suynane | 来源:发表于2018-09-06 12:04 被阅读0次

    很久以后回头再看源码,发现其初始化以及扩容过程,与之前认知有出入,记录一二。

    HashMap几个重要的属性参数:

    Entry[]  table:HashMap底层用一个Entry对象存储一组key-vlaue键值对,table作为Entry对象的数组,存储了所有的键值对(遍历操作,多是针对table来进行)

    size:HashMap的键值对的数量,也可以理解为table的长度

    loadFactor:扩容因子,默认为0.75

    capacity:容量,默认为16

    threshold:hashmap进行扩容的阀值,一般为capacity * loadFactor

    put方法主要进行如下几个操作:

    1.如果是空数组,进行数组的初始化,并计算扩容阀值threshold。

    2.判断key是否为空。

    3.计算key的hash值,并用hash值与数组的数组table位运算,来确定存放在数组中的存放位置。

    4.遍历判断是否是重复的key,如果key的hash相同且equals值相同,表示key重复,覆盖vlaue,并返回旧的value。

    5.添加Entry操作,addEntry

    put方法的源码

    结合源码写一个小例子来说明put操作和扩容的过程,以及说明达到阀值也不一定立马就扩容。给hashMap指定容量为4

    第一次put操作的时候,这时的table是一个空数组,还没有进行初始化,需要进行初始化

    第一次put

    初始化会第一次确定Entry数组table的大小,并且此方法会附带计算threshold阀值,来为后面的扩容操作做准备。

    容量的确定以及阀值得计算

    数组的的容量分配和扩容阀值得计算完成后,接下来判断key是否为空,并相应操作。

    接下来根据key的hash,将hash与table的长度进行按位&运算得到数组位置索引bucketIndex,后面会用来在此位置存放一个Entry<K,V>。

    在进行插入数组之前,需要判断是否是重复的key,如果重复,覆盖原vlaue,并返回原value。

    当上面的操作都通过之后,进行真正的插入操作addEntry,hash、key、value、bucketIndex,这些值在插入操作时候都要用到。

    创建一个新的Entry,将其插到数组中的对应位置(采用头插法),并将table的长度size加1

    其实,插入操作前,会进行容量的判断,是否达到扩容的阀值,这里需要注意,尽管已经达到阀值,但是本次确定的数组下标(或称索引)处如果未被使用,则本次操作不会进行扩容操作

    举个例子,本列中初始容量为4,因子为0.75,阀值threshold=4*0.75,等于3。

    当第四次进行put操作,此时的size等于3,size>=threshold成立,已经达到扩容的阀值。但是由于计算出来的bucketIndex等于2,而数组table[2]没有被使用,依旧不会进行扩容,扩容操作将会延缓到下一次操作

    只有当第五次put操作时,table没有了空余位置,且size大于阀值threshold,进行扩容操作:

    1.创建一个新的数组,容量是原来的两倍,作为扩容后的新数组。

    2.将原数组的值迁移搬运到新的数组中。

    3.重新计算扩容阀值

    相关文章

      网友评论

          本文标题:HashMap达到扩容阀值也不一定就开始进行扩容

          本文链接:https://www.haomeiwen.com/subject/bmtxgftx.html