美文网首页
HashMap 的构造函数分析

HashMap 的构造函数分析

作者: 小李不秃 | 来源:发表于2020-03-28 01:39 被阅读0次

    HashMap 系列文章

    前言

    上一节我们分析了 HashMap 的自定义常量的含义,这一节带大家分析一下 HashMap 的构造函数。


    HashMap 构造函数

    HashMap()

    HashMap 无参构造函数,默认 table 初始化是 16,默认的加载因子是 0.75,这个在上一讲也讲过了,DEFAULT_INITIAL_CAPACITY 是 16,DEFAULT_LOAD_FACTOR 是 0.75。


    HashMap()

    HashMap(int initialCapacity)

    HashMap(int initialCapacity),可以对容量进行设置,加载因子是 DEFAULT_LOAD_FACTOR ,调用的是下面的有参构造函数。


    HashMap(int initialCapacity)

    HashMap(int initialCapacity, float loadFactor)

    HashMap(int initialCapacity, float loadFactor),可以指定容量和加载因子。容量不可以小于 0 ,也不可以无限大。加载因子也不能是 0 ,也不能比 0 小。并且不能是 NaN (详见)。
    然后给 loadFactor 进行赋值,并且给对阈值 threshold 进行设置。我们可以看一下 tabSizeFor 方法。

    HashMap(int initialCapacity, float loadFactor)

    对于给定的容量进行计算,返回 2 的 n 次方。那这块的计算规则,我给你们讲解一下。

    tabSizeFor
    首先我们看一下运算符的优先级 (详见)

    我们知道先进行位移预算,再进行与运算,然后再给 n 进行赋值。

    这块的意思是什么,就是以你的最高位为基准,然后让后面的位置都是1。

    那我举个例子,你就明白了,

    比如 cap 是 17,那么 n 就是 17-1 = 16

    16 对应的二进制是 10000。

    那咱们一步一步的算:

    首先

    n |= n>>>1

    n >>> 1,标识 n 右移 1 位,那么 n = 01000

    10000 | 01000 = 11000

    n = 11000

    第二步

    n >>> 2, 标识 n 右移 2 位,那么 n = 00110

    11000|00110 = 11110

    n = 11110

    第三步

    得到 n = 11111

    最终就得到 n = 11111 也就是换算成十进制也就是 31,那返回结果就是 31+1 = 32

    所以不管你输入的是多少,比如十进制 100 换算成二进制就是 1100100 那么得到的结果就是 1111111 就是 127,那返回结果就是 128。

    而为什么偏要是 2 的 n 次方呢?这里提前透露一下,当进行 put 的时候,会计算 hash 值,然后进行 hash 值得优化,并且把优化后的 hash 值和 size-1 进行一个与(&)运算。这个会在后续进行更详细的讲解。

    HashMap(Map<? extends K, ? extends V> m)

    HashMap(Map map) 创建一个新的 HashMap ,加载因子是 DEFAULT_LOAD_FACTOR 。然后通过 putMapEnries 将 map 的值存储到新的 HashMap 中。

    HashMap(Map<? extends K, ? extends V> m)

    putMapEntries 方法主要分为三步

    1. 如果 HashMap 没有创建,给阈值设值。
    2. 如果 HashMap 不为 null,根据阈值判断是否需要扩容。
    3. 通过 entrySet() 获取 map 的所有键值,通过循环,用 getKey() 和 getValue() 获取键值,然后 put 到新的 HashMap 中。


      putMapEntries 方法

    总结

    HashMap 有四个构造函数,分别是:

    • HashMap()
    • HashMap(int initialCapacity)
    • HashMap(int initialCapacity, float loadFactor)
    • HashMap(Map<? extends K, ? extends V> m)

    通过构造函数可以设置容量和加载因子,容量必须大于 0 ,最大不能超过 MAXIMUM_CAPACITY,而且通过 tabSizeFor(int cap) 方法返回 2 的 n 次方,并且赋值给 threshold。threshold 是 HashMap 的阈值,在 resize() 方法初始化 table 的时候,threshold 是初始化 table 的容量大小。这个 resize() 方法在后面会详细讲解。所以为了减少扩容和 hash 冲突,我们可以在创建 HashMap 的时候提前控制容量和加载因子的大小,来提升系统的性能。

    相关文章

      网友评论

          本文标题:HashMap 的构造函数分析

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