HashMap和ConcurrentHashMap的一些总结(基于jdk1.8)

一些简单的理解,细节需要自己看源码

一.数据结构

1.HashMap
数组+链表+红黑树
2.ConcurrentHashMap
数组+链表+红黑树

二.使用场景

1.HashMap
单线程无并发的情况下(多线程会形成环形链表造成死循环)
2.ConcurrentHashMap
多线程有并发的情况下

三.设计角度

1.HashMap
在一个大的集合中快速的取到存储的值
2.ConcurrentHashMap
多线程有并发的情况下在一个大的集合中快速的取到存储的值

四.存储

1.HashMap
1)使用hash算法计算出数据应该存储的位置(数据结构的数组部分也叫位桶)
2)根据计算的结果查看是否有hash冲突来指定存储方式(直接存放/链表/红黑树)
2.ConcurrentHashMap
1)使用hash算法计算出数据应该存储的位置(数据结构的数组部分也叫位桶)
2)根据计算的结果查看是否有hash冲突来指定存储方式(直接存放/链表/红黑树) 这里使用了分段锁

五.扩容
  1. HashMap

    1)触发条件:

    a.当存放数据的数量大于当前map容量的75%(可自定义)时触发扩容(一般有put,putAll的时候触发)
    b.数组长度小于64,但是已经要产生红黑树结构(hash碰撞太严重)

    2)扩容过程

    a.扩容至当前容量的两倍(2的整数次幂)
    b.遍历数组(位桶)取值,根据数组上面数据的数据结构把数据拿出来,再通过hash算法存放到新的扩容数组里面并赋值给当前map

  2. ConcurrentHashMap

    1)触发条件:

    a.当存放数据的数量大于当前map容量的75%(可自定义)时触发扩容(一般有put,putAll的时候触发)
    b.数组长度小于64,但是已经要产生红黑树结构(hash碰撞太严重)
    c.扩容状态下其他线程对集合进行插入、修改、删除、合并、compute 等操作时遇到 ForwardingNode 节点会触发扩容

    2)扩容过程

    a.扩容至当前容量的两倍(2的整数次幂)
    b.根据CPU的核数来决定多线程扩容每条线程需要扩容的大小,如果是单核就线程扩容全部,如果是多线程每条线程最少扩容16个位桶
    c.线程扩容的时候标记扩容位(下标),每个线程负责16个,当下标减少为0的时候则扩容完成
    d.扩容数据的处理:当位桶数据为链表则根据二进制计算高低位来迁移整个链表;如果是红黑树则拆掉红黑树形成两个链表,一个链表是正常链表,另外一个链表的元素要满足形成红黑树的条件,最终成为一个链表加一个红黑树,再放到新的数组中完成扩容

参考(https://blog.csdn.net/ZOKEKAI/article/details/90051567)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值