HashMap底层原理初解

1.HashMap是干什么的?
2.HashMap的数据结构是什么样的?
3.Hash整体分析(源码查看) 源码查看方式:ctrl+N

1.HashMap是干什么的?

*HashMap是用来存储key Value的数据的

*计算机存储数据都会有自己的特定存储方式,比如数据结构:
*数组,链表,树形,图形等

*ArrayList 底层的数据结构 就是数组!
ArrayList默认容量为10,每次扩容为原来的1.5倍,如果新增后超过这个容量,则容量为新增后所需的最小容量。如果增加0.5倍后的新容量超过限制的容量,则需要所需的最小容量与限制的容量进行判断,超过则指定为Integer的最大值,否则指定为限制容量大小。然后通过数组的复制将元数据复制到一个更大(新的容量大小)的数组


*LinkedList 底层的数据结构就是链表!
*(双向链表)
2.HashMap的数据结构是什么样的?
*HashMap采用数组+链表的存储方式
*代码实现:


    *key value确实得到了存储 而且链表为单向链表

*Node[] node :数组格式


*此节点数组的大小( Default_initial_capacity)默认为2^4:16 最多为2^30 此格式必须为2^n 否则扩容后计算时会很麻烦
* 当数组容量不够用的时候 扩大 什么时候扩大?
*在用到小于16的值的时候 进行扩大 比如12 12/16=0.75
* Deafult_load_factor=0.75 是一个负载因子、加载因子(规定为0.75这个值)
*数组的容量*0.75=12 那么数组的格子用了超过12 就对数组进行扩大
*(Treeify_thresholl)链表的长度超过某个值(阈值:8)的时候,就要进行链表的变形
*变形的目的在于节省存储时间 不需要一直向下走到最后一个才进行存储
*不变形会增加时间复杂度
*会变形成为一种二叉树的一种,红黑树(平衡二叉树)

* (Untreeify_threshold) 当红黑树的节点<=6的时候,会转换为原始链表结构



*问题:
*来了一个key value之后,何去何从?
*要计算出来这个键值对在数组中的位置(16以内,默认大小2^4)
*得到一个0-15的值,然后将这个node节点就放在数组的这个位置
*两种方法得到这个数组位置:
1.Random。nextInt(16) 不推荐用
2.使用hash算法
*根据Node节点要得到一个数组的位置
(1)先得到一个整型的数 key.hashCode 3254239
(2)控制这个整型的数在0-15之间 3254239%16

*过程:
*Node{key,value...} 判断Node节点在哪个位置
*先经过数组,如果数组可以去存,就存在数组
*如果数组位置重叠,就放在下面节点的位置
*当下面节点长度超过8,就转换成红黑树结构(自平衡二叉查找树)
*红黑树典型作用是关联数组,当执行删除或插入操作时,红黑属性可能会违规,但仍能正常进行,变更少量红黑结构,并进行不超过3次的树旋转,允许进行删除等操作,但会导致了非常复杂的操作。

3.Hash整体分析(源码查看) 源码查看方式:ctrl+N

*hash算法
key.hashCode 3252112
resize(); 的一个功能是:初始化
table = new Node[default_initial_capacity];

16 16*0.75=12 数组在使用到何时的时候需要进行扩容操作
根据hash值进行一个运算,这个运算就是要真正得到Node节点在数组中的一个下标位置
hash%16

*Node hash 记录 key..hashCode 因为Node节点要去哪里 它是知道的

*hash%n

*n-1 & hash 也能得到0-15之间的值 &运算 效率更高

*数组长度 必须是2^n 16 32 64 100000000-1=011111111
*怎么样才能让hash计算结果不一样呢 高16^ 低16位 做异步运算

*else是数组原来的位置 一定有节点

(1)if 当这个节点key值相同 只需要替换掉原来的值
(2)else if 发现判断p 当前的节点是否为TreeNode(红黑树)

(3)for 链表式存储方式

*数组的格子被占用后,要随时判断 是否大于16*0.75=12 如果大于 就要进行数组扩容操作

*threshold:12
*开始的时候resize 数组在初始化的时候进行resize操作
*不仅进行数组的初始化,还要进行数组的扩容操作 16->32 双倍的扩容 保证数组的大小还是2^n



*数据节点重新进行分配:
(1)有节点,链表下面为空
(2)有节点,下面不为空,但是为红黑树
(3)有节点,下面不为空,但是为链表

*判断数组位置



java1.7前 并没有红黑树的概念

多个线程去引用一个变量 会引发线程安全的问题
可以引用同步锁 sunchronized 在一个时间段 只能执行一个线程













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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值