HashMap

HashMap

HashMap 1.7到1.8之间的变化

  1. HashMap 1.7底层是数组+链表 1.8 是数组+链表+红黑树 加入红黑树提高了查询效率 和插入效率
  2. 1.7链表使用的是头插法、1.8使用的是尾插法 因为1.8插入元素时要判断元素的个数,这就要遍历链表统计元素的个数,所以正好使用尾插法
  3. 1.7中的哈希算法比较复杂,包括右移异或运算,1.8进行了简化,因为复杂的哈希运算的目的时提高散列性,提高效率,而1.8提供了红黑树,所以可以适当简化哈希算法,节省cpu

HashMap的put流程

  1. 通过key进行哈希运算与数组长度取模得到数组小标
  2. 如果数组小标元素位置为空,则将key-value封装成entry对象(1.8是node)放入该位置
  3. 如果该元素位置不为空,则分情况讨论
    a.如果是JDK1.7
    则先判断是否需要扩容,扩容就直接扩容,不需要扩容就生成entry对象,头插法放入链表中 如果扩容 就是先生成新数组,然后遍历老数组每个位置上链表的每个元素,取key然后计算,然后将新元素放入新数组,然后将新数组赋予hashmap的table属性
    b.如果是JDK1.8
    则先判断当前位置是链表结构还是红黑树结构
    如果是红黑树,则放入对应位置,其中会判断是否存在该key 存在则更新value
    如果是链表,则遍历元素,这个过程会比较key,如果没有相同的则采用尾插法插入链表末端,然后在判断是否需要转化为红黑树
    最后判断时候需要扩容
    如果需要 扩容流程是
    先生成新数组,遍历每个链表和红黑树上的每个元素,计算其在新数组中对应的位置
    然后计算每个位置对应的元素个数,超过8则构建红黑树,将头节点放入数组中,否则将链表头节点放入 最后再赋予table属性

ConCurrentHashMap的扩容机制

首先分两个版本讲

java 1.7-------这个时候ConCurrentHashMap用的还是segment实现

  1. 每一个segment还相当于一个小型的HashMap
  2. 每个segment都会进行扩容,扩容逻辑和Hashmap类型
  3. 先生成新的数组,再将元素转移到新数组中去
  4. 扩容也是每个segment内部单独判断的,是否超过阈值

java 1.8-------这个时候ConCurrentHashMap不再基于segment实现

  1. 当put时,如果正在进行扩容,那么该线程一起扩容
  2. 没有扩容则正常添加到ConCurrentHashMap其中,然后判断是否超过阈值,超过则进行扩容
  3. ConCurrentHashMap支持多线程同时扩容
  4. 扩容前也是先生成一个新的数组
  5. 转移时,先将原数组分为不同的组,将每组交给不同的线程来负责元素的转移,每个线程负责一组或多组的元素转移工作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值