八股day1——HashMap

HashMap

回答重点

  • 数组+链表+红黑树
  • 超过负载因子会*2扩容,扩容操作比较耗时
  • 尾插法,头插法在多线程中可能会形成回路,可以参考BV1n541177Ea

红黑树优化

  • 当链表长度超过8时,链表会转变为红黑树,查找复杂度从O(n)降到

    O(logn),如果树中元素低于6,则转换回链表,减少不表的树操作开销

hashCode()和equals()

  • hashCode()用于计算hash值,equals()比较两个键是否相同
  • equals()相等,对象一定相等,而hashCode()不能推出同样结论

ConcurrentHashMap

  • 是 Java 中提供的一个线程安全的哈希表实现,它在多线程环境下提供了高效的并发访问。

  • 实现思路:当塞入一个值的时候,先计算key的hash后的下标,如果计算到的下标还未有Node,就通过cas塞入新的Node。如果已经有node则通过synchronized将这个node上锁,这样别的线程就无法访问这个node及其之后的所有结点。若key相等替换value,否则新增一个node同HashMap。

  • 结点维护:baseCount可以理解为总结点数,如果修改成功就直接返回,如果失败说明此时有线程在竞争,这时启动planB。既每个线程单独维护自己的数量CounterCell,结果为baseCount+所有CounterCell。好处为减少并发场景对单个成员变量的竞争压力,提高了并发度,也就是LongAdder思想。

cas操作

  • 原子操作,compare and swap,它比较内存中的某个值是否为预期值,如果是则更新为新值,否则不做修改。

  • 失败重试:如果不等,说明其他线程修改了该值,cas操作失败,一般会利用重试,直到成功。

    优点:

    • 无锁并发,比用锁的性能更高
    • 原子性,性能安全

    缺点:

    • 单变量限制
    • ABA问题:如果一个变量值从A->B->A,cas无法检测到这种变化,可能导致错误(可解决:如引入时间戳检测到变量的变化)
  • Atomic类中封装了CAS操作

为什么jdk1.8对HashMap进行了红黑树的改动

  • 1.8之前,用链表来解决hash冲突。当hash冲突较多时,链表中的元素增多,查找,插入和删除的时间复杂度从O(1)退化为O(n)。而红黑树的时间复杂度为O(logn)。

  • 除了链表长度影响树化,实际上还与数组长度有关。某个桶中元素数量>=8,且数组长度大于等于64,则树化。

  • 为什么树化有数组条件限制?因为树化有开销。

  • 为什么不能舍弃链表就用红黑树?因为红黑树结点大小是链表结点大小的两倍。

posted @   Sha11ow  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示