HashMap 的构造函数分析

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 的时候提前控制容量和加载因子的大小,来提升系统的性能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容