2020-10-15

[hashmap的底层实现TOC]
hashmap的底层是数组加单向链表存放数据的,它的默认长度是16,加载因子是0.75,扩容阈值是默认长度乘以加载因子;
比如我们通过无参构造方法实例化出hashmap时,会默认给hashmap加载因子设置成0.75,这时hashmap并没有开辟空间,只有在调用put方法放值是才开始开辟空间。
put方法开辟空间后
第一步,判断传入的键是否是null,如果是null,直接放入到node中,并返回。
第二步,如果存放的键不是null, 接着往下走,下面判断条件是当前要存放的值是否在hashmap中存在,如果存在直接执行覆盖操作。
第三步,如果要存放的值不存在,就循环单向链表,比对单向链表中的每个值是否和传入的值一致,如果一致,直接跳出循环,拿新的值翻盖掉老值。如果单向链表的值都没有和新传入的值一致,那就在单向链表的最后面插入新值,在插入新值后进行判断,判断单向链表的长度是否超过8个,如果超过8个,单向链表就会变成红黑树,这样的目的是为了提升查询效率。
第四步,判断size的长度是否大于阈值(阈值=数组长度*加载因子),如果大于阈值就进行扩容。
在put方法最后有一个++modCount的属性,这个属性在put、get、remove方法中都有使用,这个属性是集合的一个fail fast机制,是为了防止集合多线程情况下,一个线程正在操作迭代器的foreach查询时,如果有其它线程执行增删改的操作,就会造成了查询数据不一致,这时查询就会抛异常,以保证数据的安全性。
modCount类似于一个乐观锁的机制,它只能保证数据在一定情况下安全,但不能保证绝对安全,所以hashmap还是一个线程非安全的。

为什么要设置0.75的扩容因子?
设置0.75的扩容因子是解决“哈希冲突”和“空间利用率”矛盾的一个折衷方案。跟数据结构要么查询快要么插入快一个道理,hashmap就是一个插入慢、查询快的数据结构。
加载因子是表示Hash表中元素的填满的程度。加载因子越大,填满的元素越多,空间利用率越高,但hash冲突的几率就会加大,冲突的记录大会造成查找的成本高。
加载因子越小,填满的元素越少,冲突的机会减小,但空间浪费多了,但查找的成本小了很多。
所以,0.75是在 "冲突的几率"与"空间利用率"之间寻找一种平衡与折衷。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值