栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java面试宝典:你一定不知道的 HashMap

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java面试宝典:你一定不知道的 HashMap

 考点:
     1. HashMap的底层数据结构?
     2. HashMap的存取原理?
     3. Java7和Java8的区别?
     4. 为啥会线程不安全?
     5. 有什么线程安全的类代替么?
     6. 默认初始化大小是多少?为啥是这么多?为啥大小都是2的幂?
     7. HashMap的扩容方式?负载因子是多少?为什是这么多?
     8. HashMap的主要参数都有哪些?
     9. HashMap是怎么处理hash碰撞的?
     10. hash的计算规则?
  • #负载因子

  当 负载因子 < 0.75 时,数组中元素较少时即触发扩容,时间效率提升(链表相对较少,取值直接hash),空间利用率降低

  当 负载因子 > 0.75 时,数组中元素较多时才触发扩容,时间效率降低(链表相对较多,取值需进行查找),空间利用率提升

  当 负载因子 = 0.75 时,空间利用率较高,可避免相当多的 hash 冲突(降低了链表/红黑树的高度),且取值基本可直接hash

  • #init

  阿里巴巴插件规范:在初始化HashMap时尽量赋初值且值为2^n

  HashMap默认初始长度为 1<< 4 (16)

  索引的计算方式为 `index = (n - 1) & hash` _(其中 n = key.length())_

  所以为了尽量使key的对应索引值分布均匀,可将值设为 2^n 使得 (n - 1) = 0b1111111...,index 的值等同于hashCode的后几位。即只要输入的 hashCode 本身分布均匀,hash算法结果就是均匀的(减少干扰)

  这是为了实现均匀分布。

  • #put

  HashMap使用链表+数组的方式储存节点 (1.7 Entry 1.8 Node)

  在Java8以前,对于重复数据采用的是头插法(作者认为新插入的值被查找的可能性更大),从Java8开始改用尾插法

  HashMap进行扩容时先将数组长度扩容,然后枚举数组所有位置对存在的列表的所有节点重新计算哈希值,当使用头插法时可能导致链表倒序,多线程下还有形成环形链表的风险

1. 原链表

 

2. 倒序

  3. 闭环

 

  因为扩容前后结点顺序不变,故1.8以后使用尾插法时不会出现上述两种情况。但仍无法保证线程安全(方法未加锁) 

参考文章

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/281146.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号