• HashMap 和 ConcurrentHashMap,Java1.8版本


    1. HashMap

    Entry,一对kv就是一个Entry,还包括一些next指针,用来解决散列冲突。

    table,内部用来存储Entry的数组,resize时候table会成倍扩容。

    容量,table数组的长度。

    装填因子,当key的数量大于table.length*装填因子就要进行扩容,默认75%。

    resize操作,同步的重新计算一遍hash值对应的新的slot

    Put操作

    和所有hashmap一样,都是计算hash值,检查容量,映射到slot。当发生冲突的时候会往entry链表的后面插入。

    不过,java还做了一个优化,这个链表长度当大于8个的时候会把他优化成一个有序的Tree。

    Get操作

    根据hash值找到slot,然后比较第一个Entry是不是要找的kv,不是的话,就沿着next指针的Entry往下找。

    如果,发现是个Tree不是链表,直接做有序的查找

    2. ConcurrentHashMap

    以下和HashMap相同的地方就不说了

    问题,ConcurrentHashMap多线程情况下怎么初始化table,以及table在多线程情况下resize

    解决,

    有一个sizeCtl的属性,这个属性只可能是0或者-1,通过CAS,只有一个线程把他设置成-1。

    其他没设置成功的线程调用Thread.yield,原话是“lost initialization race; just spin”

    问题,Put的时候slot之前没有值,怎么防止多个线程同时设置新值

    解决,

    尝试用CAS更新一次这个空的位置,更新失败的时候,对slot上的第一个Node加锁,用插入到链表或者TreeNode

    问题,Put以后要size++

    解决,

    这里没有使用AtomicInteger,而是把每个slot对应一个CounterCell代表这个slot下Entry的数量,这里没读懂为什么使用CounterCell

    问题,resize相关的策略

    解决,

    之前用装填因子和数量来判断是否需要resize,java8是通过是否有散列冲突来扩容。

    与redis的策略一样,java8也是采用渐进性哈希的方式。

  • 相关阅读:
    Json对象和字符串互转
    JSNOP调用。。。
    org.hibernate.LazyInitializationException: could not initialize proxy no Session
    myeclipse生成注解实体
    jquery判断浏览器和版本
    JSTL XML标签库
    ORACLE 月份不全,补全月份的sql
    js 上下左右键控制焦点
    google gson使用
    js判断undefined类型
  • 原文地址:https://www.cnblogs.com/23lalala/p/5221496.html
Copyright © 2020-2023  润新知