HashMap 是一种散列表,它存储的内容是键值对(key-value)映射 。在 HashMap 中,每个键(key)映射到一个值(value) 。散列表的工作原理是:当通过 put() 方法将键值对存储在 HashMap 中时,HashMap 首先会根据键的 hashCode 值来计算出存储位置,然后将键值对存储在该位置上 。当通过 get() 方法获取键值对时,HashMap 再根据键的 hashCode 值来获取存储位置,然后返回该位置上的值 。
hash算法的优化:对每个hash值,在它的低16位中,让高低16位进行异或,让它的低16位同时保持了高低16位的特征,尽量避免一些hash值后续出现冲突,大家可能会进入数组的同一位置 。
文章插图
对寻址算法的优化
(p = tab[i = (n - 1) & hash]// (n-1) & hash ==> 数组里的一个位置
hash & (n-1) 效果是跟hash对n取模是一样的,但是与运算的性能要比hash对n取模要高很多 。数组的长度会一直是2的n次方,只要他保持数组长度是2的n次方 。- 寻址为什么不用取模?
也就是说,哈希表长度 length 为 2 的整次幂时,hash & (length - 1) 的计算结果跟 hash % length 一样,而且效率还更好 。
- 为什么不直接用 hashCode() 而是用它的高 16 位进行异或计算新 hash 值?#
寻址算法的优化:用与运算替代取模,提升性能 。(由于计算机对比取模,与运算会更快) 。
在 JDK1.8 中,HashMap 的结构由数组和链表(或红黑树)组成 。数组是 HashMap 的主体,链表和红黑树则是为了解决哈希冲突而存在的 。从上图可以看出,HashMap 由一个个 Node 节点组成,每个节点包含了键值对的信息,以及指向下一个节点的指针 。HashMap 内部维护了一个数组 table,每个元素都是一个链表的头节点(或者是一个红黑树的根节点),当多个键映射到同一个位置时,它们会被存储在同一个链表中(或者是同一个红黑树中) 。当链表长度超过阈值(默认为 8)时,链表就会被转换成红黑树(如下图),这样可以提高查找效率 。如果红黑树的节点数小于等于6,那么就将红黑树转换回链表,以节省空间 。
文章插图
转换红黑树
在 JDK1.8 中,HashMap 还引入了一个新的概念,叫做负载因子(load factor),它是指哈希表中键值对的数量与数组长度的比值 。当键值对的数量超过了负载因子与数组长度的乘积时,就会触发扩容操作,HashMap 会自动将数组长度扩大一倍,并将原来的键值对重新分配到新的数组中 。这样做的目的是为了保证散列表的性能,因为当负载因子过高时,散列表的性能会急剧下降 。
【HashMap 的基础结构,必须掌握!】
推荐阅读
- 日200亿次调用,喜马拉雅网关的架构设计
- 为什么我更喜欢基于主干的开发
- 深度学习时代的稀疏特征提取和匹配
- 新证据!网攻西工大的神秘黑客身份被锁定,“间谍软件”是关键!
- 零拷贝并非万能解决方案:重新定义数据传输的效率极限
- 换锦花和彼岸花的区别 换锦花花语
- 被前妻骗走5千万,6个孩子没一个亲生的,他这一生都是“大戏”
- 看《西出玉门》人物关系图,了解剧中错综复杂的情感纠葛
- 兰花的花语和象征意义 蓝色的兰花的花语和象征意义
- 紫罗兰的花语和传说故事 紫罗兰的花语和传说