zoukankan      html  css  js  c++  java
  • 集合类

    一、HashMap

    创建一个HashMap:

    1. HashMap对象创建时,实际容量为长度为0的Entry数组
    2. put数据时:
      2.1 检测table数组长度是否为空数组
        2.1.1 如果是空数组,根据初始化容量大小capacity计算出大于等于capacity的2的n次方的值
        2.1.2 根据上面计算出来的2的n次方的值,创建Entry数组
      2.2 如果key为null,则直接将数据存储在Entry数组的第一个元素(key为null的值只能存储一个)
      2.3 如果key不为null:
        2.3.1 根据key计算出hash值,然后根据hash值和数组长度减1计算出索引位置(说明:数组长度是2的n次方,2的n次方减1的二进制数全是1,这样有利于hash散列均匀)
        2.3.2 从Entry数组中找到索引位置的数据,遍历链表,如果key相同,则替换value
        2.3.3 如果索引位置的Entry链表上的数据,没有key相同的,则准备将key-value添加到Entry数组中
        2.3.4 添加到Entry数组之前,先检查是否需要进行扩容(扩容为原来的2倍):遍历所有的元素,重新计算索引位置,hash冲突时在链表头插入(不安全,形成环形链表)
        2.3.5 创建新的Entry对象,插入到数组

    二、ConcurrentHashMap

    1. 创建ConcurrentHashMap:
      1.1 根据concurrencyLevel参数(默认为16)计算Segment数组长度(说明:数组长度是大于concurrencyLevel的最小的一个2的n次方数)
      1.2 根据初始化容量大小(默认是16)计算出Segment内table数组的长度(说明:table数组长度=初始化容量/Segment数组长度,如果计算的结果小于2,则用2作为数组长度)
      1.3 创建Segment数组,并且创建数组的第一个Segment对象
    2. put数据:
      2.1 key或value为null,则抛出NullPointerException
      2.2 根据key计算出Segments数组中的索引,如果Segments数组中该索引位置元素为null,则创建Segment对象
        2.2.1 获取Segments数组的第一个Segment对象,以该对象作为原型创建Segment(参考数组长度、加载因子)
        2.2.2 创建好Segment对象后通过CAS方式,插入到Segments数组
      2.3 数据put到Segment对象的table数组(HashEntry[]):
        2.3.1 通过ReentrantLock对Segment对象加锁,如果加锁失败,则循环重试加锁(说明:如果内核数大于1,则最多重试64次,否则重试1次)
        2.3.2 根据key计算出table数组中的位置,获取table数组中的HashEntry对象
        2.3.3 如果HashEntry对象不为null,则将新put的数据加入到HashEntry的链表中
        2.3.4 如果HashEntry对象为null,则新建一个HashEntry对象
        2.3.5 检测容量是否超过0.75,如果超过则进行扩容;否则将HashEntry加入到table数组

    3. 扩容:
      3.1 计算出新的HashEntry数组长度(原数组长度*2),并创建新的HashEntry数组;
      3.2 遍历原HashEntry数组元素,计算该元素在新数组中的位置newIndex
        3.2.1 如果HashEntry只有一个元素,则在新数组的newIndex插入该元素
        3.2.2 如果HashEntry有多个元素,则遍历链表,获取到链表中最后一批新index相同的第一个元素,并插入到新数组
        3.2.3 从HashEntry链表头部遍历开始遍历,计算在新数组中的newIndex,创建一个新的HashEntry对象插入到新数组,并将新数组中原存储的对象赋值到新HashEntry的下一个节点(表头插入)

    三、CopyOnWriteArrayList

    实现原理:底层使用数组实现;当需要修改List元素(add、remove、set)时,先进行加锁,然后将原素组进行复制(Arrays.copyOf)一份进行增、删、改;如果需要从List读取数据,则不加锁直接进行读取。

    使用场景:常用在多度、少些写的场景

    是否线程安全:不完全(在进行删除操作同时读取集合最后的数据可能会出现数组越界)

  • 相关阅读:
    web-9. 动态网页与数据库-2
    web-9. 动态网页与数据库
    web-8. 多框架页面的创建
    web-7. 丰富页面的多媒体
    web-6. 组织页面的表格
    yocto术语二
    yocto术语
    linux source
    linux 添加环境变量
    ubuntu上网
  • 原文地址:https://www.cnblogs.com/wuan90/p/14418750.html
Copyright © 2011-2022 走看看