HashMap中的bucket介绍
对于 HashMap 及其子类而言,它们采用 Hash 算法来决定集合中元素的存储位置。当系统开始初始化 HashMap 时,系统会创建一个长度为 capacity 的 Entry 数组,这个数组里可以存储元素的位置被称为“桶(bucket)”,每个 bucket 都有其指定索引,系统可以根据其索引快速访问该 bucket 里存储的元素。
无论何时,HashMap 的每个“桶”只存储一个元素(也就是一个 Entry),由于 Entry 对象可以包含一个引用变量(就是 Entry 构造器的的最后一个参数)用于指向下一个 Entry,因此可能出现的情况是:HashMap 的 bucket 中只有一个 Entry,但这个 Entry 指向另一个 Entry ——这就形成了一个 Entry 链。如图 1 所示:
图 1. HashMap 的存储示意
HashMap 的读取实现
当 HashMap 的每个 bucket 里存储的 Entry 只是单个 Entry ——也就是没有通过指针产生 Entry 链时,此时的 HashMap 具有最好的性能:当程序通过 key 取出对应 value 时,系统只要先计算出该 key 的 hashCode() 返回值,在根据该 hashCode 返回值找出该 key 在 table 数组中的索引,然后取出该索引处的 Entry,最后返回该 key 对应的 value 即可。看 HashMap 类的 get(K key) 方法代码:
Java代码
- public V get(Object key)
- {
- // 如果 key 是 null,调用 getForNullKey 取出对应的 value
- if (key == null)
- return getForNullKey();
- // 根据该 key 的 hashCode 值计算它的 hash 码
- int hash = hash(key.hashCode());
- // 直接取出 table 数组中指定索引处的值,
- for (Entry<K,V> e = table[indexFor(hash, table.length)];
- e != null;
- // 搜索该 Entry 链的下一个 Entr
- e = e.next) // ①
- {
- Object k;
- // 如果该 Entry 的 key 与被搜索 key 相同
- if (e.hash == hash && ((k = e.key) == key
- || key.equals(k)))
- return e.value;
- }
- return null;
- }
从上面代码中可以看出,如果 HashMap 的每个 bucket 里只有一个 Entry 时,HashMap 可以根据索引、快速地取出该 bucket 里的 Entry;在发生“Hash 冲突”的情况下,单个 bucket 里存储的不是一个 Entry,而是一个 Entry 链,系统只能必须按顺序遍历每个 Entry,直到找到想搜索的 Entry 为止——如果恰好要搜索的 Entry 位于该 Entry 链的最末端(该 Entry 是最早放入该 bucket 中),那系统必须循环到最后才能找到该元素。
归纳起来简单地说,HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据 Hash 算法来决定其存储位置;当需要取出一个 Entry 时,也会根据 Hash 算法找到其存储位置,直接取出该 Entry。由此可见:HashMap 之所以能快速存、取它所包含的 Entry,完全类似于现实生活中母亲从小教我们的:不同的东西要放在不同的位置,需要时才能快速找到它。
当创建 HashMap 时,有一个默认的负载因子(load factor),其默认值为 0.75,这是时间和空间成本上一种折衷:增大负载因子可以减少 Hash 表(就是那个 Entry 数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的的操作(HashMap 的 get() 与 put() 方法都要用到查询);减小负载因子会提高数据查询的性能,但会增加 Hash 表所占用的内存空间。
掌握了上面知识之后,我们可以在创建 HashMap 时根据实际需要适当地调整 load factor 的值;如果程序比较关心空间开销、内存比较紧张,可以适当地增加负载因子;如果程序比较关心时间开销,内存比较宽裕则可以适当的减少负载因子。通常情况下,程序员无需改变负载因子的值。
如果开始就知道 HashMap 会保存多个 key-value 对,可以在创建时就使用较大的初始化容量,如果 HashMap 中 Entry 的数量一直不会超过极限容量(capacity * load factor),HashMap 就无需调用 resize() 方法重新分配 table 数组,从而保证较好的性能。当然,开始就将初始容量设置太高可能会浪费空间(系统需要创建一个长度为 capacity 的 Entry 数组),因此创建 HashMap 时初始化容量设置也需要小心对待。
HashMap中的bucket介绍相关推荐
- 03_MyBatis基本查询,mapper文件的定义,测试代码的编写,resultMap配置返回值,sql片段配置,select标签标签中的内容介绍,配置使用二级缓存,使用别名的数据类型,条件查询ma
1 PersonTestMapper.xml中的内容如下: <?xmlversion="1.0"encoding="UTF-8"?> < ...
- hashmap中的key是有序的么_HashMap?面试?我是谁?我在哪
(给ImportNew加星标,提高Java技能) 转自:卓庆森 https://www.cnblogs.com/zhuoqingsen/p/8577646.html 现在是晚上11点了,学校屠猪馆的自 ...
- HashMap中傻傻分不清楚的那些概念
转载自 HashMap中傻傻分不清楚的那些概念 很多人在通过阅读源码的方式学习Java,这是个很好的方式.而JDK的源码自然是首选.在JDK的众多类中,我觉得HashMap及其相关的类是设计的比较好的 ...
- 【java基础 12】HashMap中是如何形成环形链表的?
导读:经过前面的博客总结,可以知道的是,HashMap是有一个一维数组和一个链表组成,从而得知,在解决冲突问题时,hashmap选择的是链地址法.为什么HashMap会用一个数组这链表组成,当时给出的 ...
- 为什么HashMap中链表转红黑树的阀值是8?
在JDK1.8以后,HashMap中引入红黑树,主要原因为: 当一个桶(Bucket)中的元素过度填充时,链表的查找效率将会大大下降,因此在适当的时候,转换链表为红黑树,可以在桶过度填充时提高查询效率 ...
- HashMap 中那些精妙绝伦的设计
点击上方关注 "终端研发部" 设为"星标",和你一起掌握更多数据库知识 一.HashMap构造器 HashMap总共给我们提供了三个构造器来创建HashMap ...
- HashMap 中 hash 冲突的解决方法及原理分析
我们最先衰老的不是容貌,而是不顾一切的闯劲.有时候,要敢于背上超出自己预料的包袱,真的努力后,你会发现自己要比想象的优秀很多. HashMap冲突的解决方法比较考验一个开发者解决问题的能力. 在Jav ...
- HashMap中的位运算
Java 8 中 HashMap 的实现使用了很多位操作来进行优化.本文将详细介绍每种位操作优化的原理及作用. Java 中的位运算 位操作包含:与.或.非.异或 移位操作包含:左移.右移.无符号右移 ...
- Java中List集合介绍(炒鸡详细呦)
Java中List集合介绍 文章目录 Java中List集合介绍 1,Java集合介绍 2,List介绍 2.1 ArrayList集合 2.2 LinkedList集合 3,List常用方法 3.1 ...
最新文章
- python抓包工具_「docker实战篇」python的docker爬虫技术-fiddler抓包软件详细配置(七)...
- 微信小程序WebSocket实现聊天对话功能完整源码
- 四十三、文件存储空间管理
- Java学习之while语句
- 台达变频器s1参数设置_【智】台达变频器计数输入功能接线和参数设置详解
- 王道计算机考研 数据结构 (查找-上)
- MTM:matlab实现2参数解析
- 4.0.13 mysql 注入_Windows2000下整合Mysql4.0.13与Tomcat4.1.24搭建Jsp环境
- mysql workbench 监控_mysql 使用workbench工具,表状态为read only的解决方法
- 常量(const)和只读变量(readonly)
- python爬虫获取url_Python爬虫如何获取页面内所有URL链接?本文详解
- 10038 mysql,关于MySql 10038错误的完美解决方法(三种)
- 开发了一套python的七牛sdk
- 卫星导航开源代码汇总
- 16种床上动作的内涵图,你都看懂了吗?
- 学习python表情包_我用Python一键保存了半佛老师所有的骚气表情包
- table 点击文字按钮预览图片
- Matlab使用中遇到的一些脑残问题。
- android开发-验证邮箱输入是否合法
- Edge 安装 CSDN 浏览器助手
热门文章
- PCL点云库(Point Cloud Library)简介
- 小笨狗的编程感悟(序言)
- android中文乱码的解决办法
- HCIE 面试资料-BFD/NSF/NSR/NTP
- taobao.trade.fullinfo.get( 获取单笔交易的详细信息 )、淘宝店铺卖出订单详情接口,淘宝店铺订单明文接口,淘宝店铺订单解密接口
- 读《史蒂夫•乔布斯传》(二)
- anaconda使用心得
- 公司监控显示无网络连接服务器,监控显示无网络视频什么原因
- TTL,CMOS,LVTTL,LVCMOS电平标准
- 用Python写个桌面挂件,手把手带你做只桌面宠物~