美文网首页
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 的构造函数分析

    HashMap 系列文章 HashMap 的自定义常量分析 HashMap 的构造函数分析 HashMap 的 h...

  • HashMap 的自定义常量分析

    HashMap 系列文章 HashMap 的自定义常量分析 HashMap 的构造函数分析 HashMap 的 h...

  • HashMap了解一下

    前言 HashMap HashMap类继承图 HashMap属性 HashMap构造函数HashMap(int i...

  • HashMap 源码分析

    构造函数 HashMap 提供了三个构造函数和一个拷贝构造函数: 构造函数 这个构造方法需要提供两个参数,init...

  • HashMap源码

    1. JDK8 HashMap 示意图 2. HashMap的构造方法 不带参的构造函数 带参数构建hashmap...

  • HashMap于LinkedHashMap

    HashMap HashMap是数组加上单链表的形式 # 构造函数 # put # get # remove # ...

  • HashMap源码解析

    构造方法 HashMap提供了三个构造函数 HashMap():构造一个具有默认初始容量 (16) 和默认加载因子...

  • JUC-Set

      HashSet构造函数:默认容量为16的HashMap。(底层是HashMap)   HashSet的add方...

  • 源码之HashMap构造函数底层分析

    基于 1.8 HashMap在JDK1.8之前是由数组加链表组成的,其中数组是主体,链表则是为了解决哈希冲突存在的...

  • HashMap自定义总结

    HashMap总结: hashmap的实质是数组(主结构)+链表+红黑色 1.构造函数设置默认的loadFacto...

网友评论

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

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