• java hashmap 浅出深入


    简介

    一般集合和map的底层原理实现可能会被面试官问到.

    参考链接

    https://www.bilibili.com/video/BV1oE411n7ug?from=search&seid=4551060475011719922
    https://www.bilibili.com/video/BV1kJ411C7hC?from=search&seid=11022586264795253983
    https://zhuanlan.zhihu.com/p/143826469
    https://blog.csdn.net/g6U8W7p06dCO99fQ3/article/details/104681428/ hashmap死循环

    参数

    1. DEFAULT_LOAD_FACTOR

    static final float DEFAULT_LOAD_FACTOR = 0.75f; 负载因子
    2. 门限

        // (The javadoc description is true upon serialization.
        // Additionally, if the table array has not been allocated, this
        // field holds the initial array capacity, or zero signifying
        // DEFAULT_INITIAL_CAPACITY.)
        int threshold;
    

    门限计算公式
    threshold = 数组长度 * 负载因子;

    size

    size 是HashMap中实习存在的键值对数量

        /**
         * The number of key-value mappings contained in this map.
         */
        transient int size;
    

    modCount

    hashmap 发生结构变化的次数.

        /**
         * The number of times this HashMap has been structurally modified
         * Structural modifications are those that change the number of mappings in
         * the HashMap or otherwise modify its internal structure (e.g.,
         * rehash).  This field is used to make iterators on Collection-views of
         * the HashMap fail-fast.  (See ConcurrentModificationException).
         */
        transient int modCount;
    

    INITIAL_CAPACITY

        /**
         * The default initial capacity - MUST be a power of two.
         */
        static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
    

    初始化容量为16.

    为什么选用2的幂次

    因为 比如16: 1 0000
    16 - 1 = 0 1111
    使用这个对hashcode产生的书进行与操作 可以得到16以内的数

    hashCode 如何将高位也进行与操作 减少冲突

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

    hashmap 1.7 采用头插法, 1.8 采用尾插法 为什么

    因为每次都要查询链表是不是8个, 所以查询结束直接尾插法,效率较高

    HashMap 发生死循环的一个重要原因是 JDK 1.7 时链表的插入是首部倒序插入的,而 JDK 1.8 时已经变成了尾部插入,有人把这个死循环的问题反馈给了 Sun 公司,但它们认为这不是一个问题,因为 HashMap 本身就是非线程安全的,如果要在多线程使用建议使用 ConcurrentHashMap 替代 HashMap,但面试中这个问题被问的频率比较高,所以在这里就特殊说明一下。

    1.8 每次链表长度到8都会扩容吗

    不会哦. 有一个64的参数, 如果没有达到64的话, 会先进行扩容.

    TIPS

    • hashmap 采用了数组 + 链表 + 红黑树 jdk.18的存储结构.

    • hashmap 数组部分称为哈希桶. 当链表长度大于等于8时, 链表数据将以红黑树的形式进行存储, 当长度降到6时, 转成链表.

    • 链表的时间复杂度为O(n)

    • 红黑树的时间复杂度为O(log n)

    • 当插入的对象大小超过临界值时, HashMap将新建一个桶数组并重新赋值. 此时, 桶数组是原来的两倍, 门限也是原来的两倍. 然后从新赋值

    参考链接

    https://blog.csdn.net/leisure_life/article/details/108482840 对于第一个元素put所进行的操作.

    推荐阅读

    https://www.cnblogs.com/zwh0910/p/14354328.html resize() 代码分析
    https://www.cnblogs.com/shujiying/p/12357452.html resize() 图形化显示

    Hope is a good thing,maybe the best of things,and no good thing ever dies.----------- Andy Dufresne
  • 相关阅读:
    360随身WiFi使用问题解决,无法在没有网络的电脑上使用
    np问题(大数阶乘取模)
    传球(概率问题)
    区间平均值(逆序对)
    完全平方数最大
    计算毫秒
    祖玛游戏
    后缀最大值
    Blah数集(双指针单调队列)
    逢低吸纳(最长下降子序列+方案数+高精度)
  • 原文地址:https://www.cnblogs.com/eat-too-much/p/14789795.html
Copyright © 2020-2023  润新知