Java容器详解二(HashMap)

1. 底层存储
在jdk1.8中,HashMap的哈希桶有两种存储结构,一种是单向链表,一种是红黑树,当哈希桶里面的节点个数大于8个的时候转为红黑树,以提高查询效率。哈希表的是一个数组,如下。

transient Node<K,V>[] table;

其初始化的大小为16,以后每次扩容增加一倍,哈希表的数组大小一定是2的幂次倍,因为一个哈希值散列的时候可以用hash&(length-1),如果length数组长度为2的幂次倍,则该表达式计算的值就可以把hash值转换为0到length-1范围内的数作为数组索引,因此可以快速计算出一个hash值所对应的数组索引。
其完整的结构图如下

图1 哈希表底层存储结构原理图

Node就是HashMap的一个内部类,存储的数据实体,一个键值对,上图中的一个黑点就是一个Node对象。
当一个HashMap内的Node数量超过临界值时会触发扩容,table的容量变为原来的2倍,临界值是threshold = length * Load factor决定的,即数组长度和负载因子,负载因子默认0.75,数组长度默认16,负载因子一般不需要调整,除非特殊情况,比如,空间非常宽松而对时间要求较高可以调低负载因子,让散列更分散。
当扩容发生时,JDK1.8版本做了优化,扩容后的容量变为原来的2倍,原来的节点的哈希值要么不变,要么比原来大oldCap,原理如图所示
图2 变化原理图

HashMap不是线程安全的,在多线程中应该尽量避免使用,最好使用线程安全的ConcurrentHashMap类,因为HashMap可能在扩容的时候多线程下产生循环链表
2. 添加元素

  1. 首先用过对象的hashCode方法返回哈希值。
  2. 然后调用hash函数对哈希值进行处理,主要是进行高位运算,是为了减少冲突,尽量防止不同的对象产生相同的哈希值。
  3. 根据哈希值来映射到数组相应索引位置,这里数组的长度一般都是2的幂次方,这样就可以通过一次与运算运算出来数组索引位置,在本文第一部分底层存储结构已经分析过了。
  4. 存储对象,存储对象分为两种情况,这取决于底层存储结构,分为链表结构和红黑树结构。
  5. 判断容器中存放的对象数量是否超过了容器的临界值,如果超过则进行扩容操作。

3. 扩容操作
当判断容器中的对象数量超过临界值的时候就会触发扩容操作,根据第一小节的内容可以知道,HashMap底层的存储结构是采用数组的结构。扩容的时候步骤如下

  1. 首先按照条件来计算扩容后的大小,一般每次扩大为原来2倍,然后更新临界值,
    2.根据计算出来的容量大小new一个新的数组
    3.重新计算原来所有节点的哈希值,然后插入到相应的数组索引下。jdk1.8版本在这里做了一个优化,原来是把所有的节点重新计算哈希值,这里是根据了一个特性,因为数组长度增长的固定的倍数,2倍,所以所有的节点索引要么不变,要么是该索引加上原来的数组长度,其原理如2所示,其取决于该对象的哈希值的一个二进制位,这个二进制位在那个数组长度变为原来2倍的那个由0变为1的二进制位。就是图中如下几位。


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

推荐阅读更多精彩内容