zoukankan      html  css  js  c++  java
  • HashMap

      传送门:Java 8系列之重新认识HashMap

      HashMap 里面是一个数组,然后数组中每个元素是一个单向链表。

      链表中存储的是一个个Node 节点, Node 包含四个属性:key, value, hash 值和用于单向链表的 next。

    1.基本属性

        // 节点数组, 数组长度始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍
        transient Node<K,V>[] table;
        // 存储的元素个数
        transient int size;
        // 扩容的阈值,等于 capacity * loadFactor
        int threshold;
        // 负载因子,默认为 0.75
        final float loadFactor;
        // 默认数组长度 16
        static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
        // 链表长度大于 8  时链表结构转为红黑树
        static final int TREEIFY_THRESHOLD = 8;

    2. put()

    2.1 计算数组下标

      根据键(Key)的hash值 除以数组长度, 计算出此节点存储在数组的位置

      一般计算方式为 key.hash() % table.length 

      当数组长度为 2^n 时, key.hash() & (table.length-1) 等价于 key.hash() % table.length, 但是位运算的效率远远高于取余

    2.2 判断key相等

      确定数组下标后, 遍历该数组下标的单项链表, 根据 == 或者 key的equals() 判断键是否相等, 若存在相等的键, 则直接覆盖value,否则新增节点

    2.3 结构转换

      当单向节点的长度大于8时,链表结构转化为红黑树

    3. 扩容

      Java7 是先扩容后插入新值的,Java8 先插值再扩容

      扩容后的数组长度为原数组长度的2倍

      扩容后需要重新计算节点在数组中的位置.

      原数组下标  =  hash & oldSize 

      新数组下标  = hash & 2 * oldSize

      新数组的下标结果 会比 原来的下标结果 多一位0或1(二进制只能为0或1), 为0时表示还在原来的数组位置, 为1时表示原下标位置+原数组长度

    4. 多线程下扩容的环形引用问题(死循环)

      当单向链表的相邻的两个节点扩容后还在同一个链表, 且位置互换, 则可能出现环形引用的问题.

  • 相关阅读:
    Django测试开发-4-django3.0.3报错:/mysql ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3
    Django测试开发-3-新建一个Django工程
    Django测试开发-2-创建虚拟环境
    Django测试开发-1-MVC/MVT的概念
    sqlserver中复合索引和include索引到底有多大区别?
    PLSQL开发笔记和小结(转载)
    PL/sql语法单元
    jquery 获取下拉框值与select text
    jquery 事件
    jquery dom操作
  • 原文地址:https://www.cnblogs.com/virgosnail/p/9497537.html
Copyright © 2011-2022 走看看