HashMap 的构造函数分析
HashMap 系列文章
- HashMap 的自定义常量分析
- HashMap 的构造函数分析
- HashMap 的 hash 算法和寻址地址的优化
前言
上一节我们分析了 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 方法。
对于给定的容量进行计算,返回 2 的 n 次方。那这块的计算规则,我给你们讲解一下。
首先我们看一下运算符的优先级 (详见)
我们知道先进行位移预算,再进行与运算,然后再给 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 方法主要分为三步
- 如果 HashMap 没有创建,给阈值设值。
- 如果 HashMap 不为 null,根据阈值判断是否需要扩容。
-
通过 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 的时候提前控制容量和加载因子的大小,来提升系统的性能。