HashMap

在jdk1.7版本其底层结构是:数组+链表
在jdk1.8版本之后底层结构修改成为:数组+链表+红黑树

在扩容机制上:
jdk1.7:当满足扩容条件后-->其初始默认的容量为16,每次扩容都×2;(只有在添加第一个元素时,才会初始化一个数组:长度为16)
其原因是:HashMap在扩容时选择了位运算。当向集合中添加元素时,它将使用(n-1) & hash的计算方法来获得元素在集合中的位置。只有当相应位置的数据都为1时,运算结果也为1。当HashMap的容量是2的n次幂时,(n-1)的2进制也就是1111111111这样形式的。这样,在用添加元素的hash值进行位运算时,可以充分散列,使添加元素均匀分布在HashMap的各个位置,减少hash碰撞。*

jdk1.8:在扩容是也是创建一个新的数组,然后将原来数组中的元素进行复制;但是需要注意的是,若原来数组位置上是一个树;在将树上的元素复制到新的数组中时,会重新计算位置那么可能发生的情况就会存在很多
1.一棵树拆成了两个链表,或者很多的散列元素
2.一棵树 拆成了两棵树
3.一棵树还是一棵树
.......
生成红黑树的条件-->数组长度大于64,链表长度大于8;

HashMap的构造方法
存在有参构造,new Hash(初始的数组长度,加载因子)
存在无参构造---->调用了带参构造默认的给初始长度和加载因子赋值了

 /**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16//默认的初始容量
 /**
     * The load factor used when none specified in constructor.
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认的加载因子
/**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;//数组的最大容量

添加数据时,先根据key算hash;然后根据hash放到数组中;

1.但是直接以算出来的hash值作为索引的下标是不可取的;
原因是:这样会以hash算法算出来的下标会过大,这样就会导致数组过大;
采取的办法是,算出来的hash再进行一次位运算,得到索引的下标,然后放大数组中,若算出来数组索引的位置是没有元素的就直接存放,若已经有元素了就会形成一个链表,这个时候就需要进行链表的添加了;
在1.7版本中采用的是头插法(https://www.cnblogs.com/xuzhidong/p/16852982.html):
2.需要注意的是,若是直接采取头插法,那么放进去的元素就会找不到,因为,形成的链表是一个单向链表,且在数组下标位置存放的是链表的尾部元素,直接存放会导致新进的元素没有指针指向;
所以新添加的元素(的引用--地址值)会直接占据原来数组下标位置(也就是"移动")-----注意的是在数组中存放的并不是该元素,而是该元素的引用,元素的本身实际上是在堆中的;
结论头插法配合"移动"才能实现数据的添加;

//java伪代码的实现
table[index] = new Node("第一个添加的元素",null);
table[index] = new Node("第二个添加的元素",table[index]);//就在这一步完成了类似"移动"的代码

HashMap类中的threshold(阈值),这个属性是用来判断是否进行扩容的;
注意的是阈值的计算不是使用HashMap类中的size属性×加载因子,而是使用数组的长度×(loadFactor)加载因子;
size是指整个数组加上链表的中的元素,并非数组的长度;

本文作者:鸽宗

本文链接:https://www.cnblogs.com/xuzhidong/p/16815292.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   鸽宗  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示
  1. 1 水星记 REOL
水星记 - REOL
00:00 / 00:00
An audio error has occurred.

作词 : 郭顶

作曲 : 郭顶

编曲 : 郭顶

监制 : 郭顶

着迷于你眼睛

银河有迹可循

穿过时间的缝隙

它依然真实地

吸引我轨迹

这瞬眼的光景

最亲密的距离

沿着你皮肤纹理

走过曲折手臂

做个梦给你

做个梦给你

等到看你银色满际

等到分不清季节更替

才敢说沉溺

还要多远才能进入你的心

还要多久才能和你接近

咫尺远近却

无法靠近的那个人

也等着和你相遇

环游的行星

怎么可以

拥有你

这瞬眼的光景

最亲密的距离

沿着你皮肤纹理

走过曲折手臂

做个梦给你

做个梦给你

等到看你银色满际

等到分不清季节更替

才敢说沉溺

还要多远才能进入你的心

还要多久才能和你接近

咫尺远近却

无法靠近的那个人

也等着和你相遇

环游的行星

怎么可以

拥有你

还要多远才能进入你的心

还要多久才能和你接近

咫尺远近却无法靠近的那个人

要怎么探寻

要多么幸运

才敢让你发觉你并不孤寂

当我还可以再跟你飞行

环游是无趣

至少可以

陪着你