• java 14 HashMap 源码学习笔记


    1. TREEIFY_THRESHOLD 常量为什么是 8 ?

    参考

    https://www.cnblogs.com/linghu-java/p/10598758.html

    https://www.v2ex.com/t/651978

    1.1 为什么要从链表转成红黑树

    链表查找性能是O(n),而树结构能将查找性能提升到O(log(n))

     

    1.2 为什么一开始不用红黑树

    • 当链表长度很小的时候,即使遍历,速度也非常快,但是当链表长度不断变长,肯定会对查询性能有一定的影响,所以才需要转成树。
    • TreeNodes占用空间是普通Nodes的两倍,所以只有当bin包含足够多的节点时才会转成TreeNodes

     

    1.3 TREEIFY_THRESHOLD 常量为什么是 8

     * Because TreeNodes are about twice the size of regular nodes, we
     * use them only when bins contain enough nodes to warrant use
     * (see TREEIFY_THRESHOLD). And when they become too small (due to
     * removal or resizing) they are converted back to plain bins.  In
     * usages with well-distributed user hashCodes, tree bins are
     * rarely used.  Ideally, under random hashCodes, the frequency of
     * nodes in bins follows a Poisson distribution
     * ( http://en.wikipedia.org/wiki/Poisson_distribution) with a
     * parameter of about 0.5 on average for the default resizing
     * threshold of 0.75, although with a large variance because of
     * resizing granularity. Ignoring variance, the expected
     * occurrences of list size k are (exp(-0.5) * pow(0.5, k) /
     * factorial(k)). The first values are:
     *
     * 0:    0.60653066
     * 1:    0.30326533
     * 2:    0.07581633
     * 3:    0.01263606
     * 4:    0.00157952
     * 5:    0.00015795
     * 6:    0.00001316
     * 7:    0.00000094
     * 8:    0.00000006
     * more: less than 1 in ten million

    理想情况下随机hashCode算法下所有bin中节点的分布会遵循泊松分布。
    根据泊松分布概率质量函数,一个哈希桶达到 9 个元素的概率小于一千万分之一



    1.4 UNTREEIFY_THRESHOLD 为什么是6
    • 必须小于TREEIFY_THRESHOLD,如果都是 8,则可能陷入(树化<=>树退化)的死循环中. 若是 7,则当极端情况下(频繁插入和删除的都是同一个哈希桶)对一个链表长度为 8 的的哈希桶进行频繁的删除和插入,同样也会导致频繁的树化<=>非树化.
    • 更低时,当链表长度很小的时候,即使遍历,速度也非常快。而TreeNodes占用空间是普通Nodes的两倍。

    2.  最小树形化阈值MIN_TREEIFY_CAPACITY

    • 当哈希表中的容量 > 该值时,才允许树形化链表 (即 将链表 转换成红黑树),否则,若桶内元素太多时,则直接扩容,而不是树形化,为了避免进行扩容、树形化选择的冲突,这个值不能小于 4 * TREEIFY_THRESHOLD

    3. hash函数--哈希值计算方法

     

    参考 https://www.zhihu.com/question/20733617

     

    由哈希值找索引的方法

        h &(length-1

    原理上是对长度取模。由于长度为2的整次幂,length-1低位都是1,相当于低位mask。h & (length-1) 相当于取 h 的低位,相当于对 len 取余。

     

    计算哈希值的方法

    static final int hash(Object key) {
            int h;
            return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
        }

     

    但是只取 h 的低位会造成严重的碰撞,于是使用扰动函数将哈希值高位的信息融合进低位,增大低位的随机性。

    用异或的原因:与& 和 或| 会偏向0或1,不均匀

     

    1.7中要做4次扰动,1.8以后只做一次,因为多了效果也不大,且引入了红黑树,即使碰撞性能也不错

    有意思的博客:面试连环炮 https://blog.csdn.net/zl1zl2zl3/article/details/105528255

    https://blog.csdn.net/zl1zl2zl3/article/details/80189728

  • 相关阅读:
    PhpPresentation ppt 导出PPT
    Springcloudalibaba学习实践(1) nacos环境搭建&Eureka Server搭建
    Springcloudalibaba学习实践(2) nacos&Eureka Server服务注册实践
    xna 3.1 to xna 4.0 conversion cheat sheet.(转)
    二分查找的越界以及边界值初始化问题
    决策树知识梳理
    论文分类及写作基础
    Cypher 入门笔记
    python字符串拼接
    Spring、Hibernate 事务流程分析Session生命周期
  • 原文地址:https://www.cnblogs.com/GY8023/p/13581718.html
Copyright © 2020-2023  润新知