三分钟让你彻底了解HashMap

三分钟让你彻底了解HashMap

HashMap原理

在jdk1.7之前是数组+链表 出现hash冲突的都存放在链表里面

在jdk1.8开始是数组+链表+红黑树 出现hash冲突的时候先存放链表里面 当链表的长度超过8的时候并且数组的长度大于64的时候才会转换为红黑树
在这里插入图片描述

底层主要有五个参数:

threshold:表示容器所能容纳的 key-value 对极限。

loadFactor:负载因子。

modCount:记录修改次数。

size:表示实际存在的键值对数量。

table:一个哈希桶数组,键值对就存放在里面

其中有两个参数可以影响 HashMap 的性能:

初始容量(inital capacity)和负载因子(load factor)。

初始容量(inital capacity)是指 table 的初始长度 length(默认值是 16);

负载因子(load factor)用指自动扩容的临界值(默认值是 0.75);

threshold是HashMap所能容纳的最大数据量的Node(键值对)个数(阈值),计算公式threshold = capacity * Load factor。当 entry 的数量超过capacity*load_factor时,容器将自动扩容并重新哈希,扩容后的HashMap容量是之前容量的两倍,所以数组的长度总是 2 的 n 次方。

初始容量和负载因子也可以修改,具体实现方式,可以在对象初始化的时候,指定参数,比如:

Map map = new HashMap(int initialCapacity, float loadFactor);

通过key获取数组的下标

不管增加、删除还是查找键值对,定位到数组的位置都是很关键的第一步,打开 hashMap 的任意一个增加、删除、查找方法,从源码可以看出,通过key获取数组下标,主要做了 3 步操作,其中length指的是容器数组的大小。

通过key获取hash的值–>对hash的值进行高位运算–>进行取模运算获取数组的下标

put的执行流程

1、判断键值对数组 table[i]是否为空或为 null,如果为空的话执行 resize()进行扩容;

2、根据键值 key 计算 hash 值得到插入的数组索引 i,如果 table[i]==null,直接新建节点添加;

3、当 table[i]不为空,判断 table[i]的首个元素是否和传入的 key 一样,如果相同直接覆盖 value;

4、如果不存在,判断 table[i] 是否为 treeNode,即 table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对;

5、如果不是树节点,那么遍历 table[i],判断链表长度是否大于 8,大于 8 的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现 key 已经存在直接覆盖 value 即可;

6、插入成功后,判断实际存在的键值对数量 size 是否超多了最大容量 threshold,如果超过,进行扩容操作;

resize扩容的过程

根据新容量,初始化一个数组–>将旧数组转移到新数组–>修改阈值,返回新数组

newTable[i]的引用赋给了 e.next,也就是使用了单链表的头插入方式,同一位置上新元素总会被放在链表的头部位置;这样先放在一个索引上的元素终会被放到 Entry 链的尾部(如果发生了 hash 冲突的话),这一点和 Jdk1.8 有区别。在旧数组中同一条 Entry 链上的元素,通过重新计算索引位置后,有可能被放到了新数组的不同位置上。

先判断原先数组的大小是否达到了2的30次方如果是就设为2^31-1不在扩容 然后将根据传入的长度创建一个新的数组

将旧数组的元素存放在新数组里面 更新阈值 放入新的数组里面的方法是头插法

1.8主要设计了树节点的分裂

get方法获取参数

,首先通过 hash()函数得到对应数组下标,然后依次判断。

1、判断第一个元素与 key 是否匹配,如果匹配就返回参数值;

2、否则判断链表是否红黑树,如果是红黑树,就进入红黑树方法获取参数值;

3、如果不是红黑树结构,直接循环判断,直到获取参数为止;

remove

通过key获取hash的值 找到对应的数组下标

1、默认判断链表第一个元素是否是要删除的元素;

2、如果第一个不是,就继续判断当前冲突链表是否是红黑树,如果是,就进入红黑树里面去找;

3、如果当前冲突链表不是红黑树,就直接在链表中循环判断,直到找到为止;

4、将找到的节点,删除掉,如果是红黑树结构,会进行颜色转换、左旋、右旋调整,直到满足红黑树特性为止;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值