HashMap原理通俗剖析

HashMap的理解

HashMap顾名思义就是通过Hash算法存的map结构的数据。虽然不正式,但是便于理解。

  1. map这就是个数据结构用来存储key value格式的
    如果写一个map的简单实现应该就是:写一个数组。数组里的元素是一个key,value的对象
    是的,HashMap的本质就是这个

  2. 那hash是什么呢?
    是写HashMap的作者用到了Hash算法
    什么时候用到的Hash算法呢?
    就是hashmap的作者实现的时候考虑性能,然后,当你put的时候把你put(key,val)的key和默认的这个数组的长度
    做了一下取模运算。算出来的模就是数组的下表
    例如:put(‘key1’,‘val1’)
    key1 % (数组的长度-1)= 3 所以这个array[3] = {key1, val1}了
    这样做的好处是,当get(key1)的时候算一下这个key的hash就知道在什么位置了,不用再遍历一遍数组了

以上就是hashmap的极简解释。
理解的过程中需要思考以下几个问题

HashMap的默认的这个数组是多长?
数据多的时候这个数组肯定会变长吧?
如果多个数据算出来的hash一样怎么办?
比如两个key的hash算出来的都是2,那数组2这个位置存哪个?怎么存的?

以下针对jdk1.8来解决这些问题

  1. HashMap存的数组多长呢?
默认是16 源码里写的
/**
 * The default initial capacity - MUST be a power of two.
 */
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

为什么是16呢,任意一个值不行吗?
数组的长度是有用的?hash的时候长度用到了啊。所以长度是2的幂次方就可以.

  1. 存的数据特别多的时候数组会变长吗?
会变长的,总是保持16的话,hash重复的会很多的。

数组怎么变长的?
有一种判断机制就是超过0.75 * 数组的长度之后,这个长度就会翻倍。

比如现在,数组是16,我存了12个数了,下一个数再存的时候,数组就变成了32。
附一点源码:
/**
 * The load factor used when none specified in constructor.
 */
static final float DEFAULT_LOAD_FACTOR = 0.75f;

所以啊。这是重点。对写代码很有用。如果我知道我要put多少个元素。我会算一下,自己定义一下长度。
不然的话可能会自动翻倍啊

你就会说了“扩就扩吧,他算出来的跟我自定义的不是一样的长度值吗?”
是这样虽然大小不变。但是会进行rehash
当时16的时候根据16hash过一次,当变成32了,之前的数据又会重新算一次。这个比较耗性能
所以写代码尽量避免自动扩容
  1. 两个hash值一样怎么办?是覆盖吗
一样的不会覆盖。会以node的形式变成链表
node是个对象里边有四个属性:
hash
key
value
next 指向下一个

会在之前的node后边插入一个node 是后插法,
jdk1.7是前插。注意理解下变成这样肯定是有用好处的.
听说过1.7时候的环形链表吗?
前插法rehash的时候,可能会形成环形链表,当你get一个key时,这个key不存在,并且hash对上了。
一个数组的key,这个里边还存了个环形链表。肯定很酸爽,会get死循环在这

  1. 如果很不幸,一个数组的某个index下边存了好多的node怎么办?会查询起来很慢吧?
这种不幸发生概率很小很小。一般不会发生。
jdk1.8之后node太多了就会转成红黑树的。

。。。
什么是红黑树?
为什么把node转成红黑树?
多少个node的时候转?

  1. 什么是红黑树?
    一种平衡二叉树的优化算法。很稳,
  2. 为什么要把node变成红黑树?
    因为链表的时间复杂度是O(n),红黑树的时间复杂度O(logn)
  3. 多少个node的时候开始转红黑树?
    8个时候。但是是有条件的。
    如果我没有定义hashmap的长度这时候,我存了9个key,很不幸,这9个key的hash值一样。难道要变红黑树?
    当然不是。红黑树很占空间的。作者肯定权衡不想转。一看现在hasmap的长度才16,还是扩容把。这时候就变成了
    32的长度,能扩容就不转红黑树的。
    什么时候就开始转红黑树,不扩容了呢?
    当长度大于64的时候就不扩容了。如果node数大于8了,就转红黑树了。因为这样性能更划算

希望能帮助到你

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰明子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值