当前位置: 首页 > news >正文

ArrayList底层结构和源码分析笔记

参考视频:韩顺平Java集合

image.png

ArrayList特点

  • ArrayList 可以加入 null,包括多个。

  • ArrayList 是由数组来实现数据存储的

  • ArrayList 基本等同于 Vector,除了 ArrayList 是线程不安全(执行效率高)。在多线程情况下,不建议使用 ArrayList

    • 例如 ArrayList 的 add() 的源码:可以发现没有 synchronized 关键词修饰
    public boolean add(E e) {  
        modCount++;  
        add(e, elementData, size);  
        return true;  
    }
    

ArrayList 源码分析(重难点🚩)

  1. ArrayList 中维护了一个 Object 类型的数组 elementData
    transient 意为短暂的;表示该属性不会被序列化

    transient Object[] elementData;
    
  2. 当创建对象时,如果使用的是无参构造器,则初始 elementData 容量为 0 (jdk7是10)

  3. 当添加元素时:先判断是否需要扩容,如果需要扩容,则调用 grow 方法,否则直接添加元素到合适位置

  4. 如果使用的是无参构造器,如果第一次添加,需要扩容的话,则扩容 elementData 为 10,如果需要再次扩容的话,则扩容 elementData 为 1.5 倍。

  5. 如果使用的是指定容量大小的构造器,则初始 elementData 容量为指定大小

  6. 如果使用的是指定容量大小的构造器,如果需要扩容,则直接扩容 elementData 为 1.5 倍。
    [[ArrayList源码分析]]

源码示例

未指定初始容量

注意将 idea 的调式工具设置一下,以便更好的观察数据:
image.png|575

  • 测试源码:

    • 观察调用构造器,创建 ArrayList 的实例的细节
    • 观察第一次添加元素(初次扩容)
    • 观察第二次添加元素(不用扩容)
    • 观察第十一次添加元素(第二次扩容)
    • 观察第十六次添加元素(第三次扩容)
    @Test  
    public void test1(){  
        ArrayList list = new ArrayList();  
      
        for (int i = 11; i <= 20; i++) {  
            list.add(i);  
        }  
      
        for (int i = 21; i < 26; i++) {  
            list.add(i);  
        }  
      
        list.add(100);  
        list.add(200);  
        list.add(null);  
        System.out.println(list);  
    }
    

创建 ArrayList 实例

  • 创建一个长度为 0 的空数组,并赋给 elementData,elementData 就是集合底层存储数据的数组。
    image.png|650

第一次添加元素“11”

  • 将 int 数据进行装箱
  • 添加这个数据“11”,要保证数组的长度至少为当前元素数+1。(size+1=1)
  • ensureCapacityInternal() 的作用就是检查数组够不够此次添加所需的容量,如果不够,则扩容,更改 elementData ,将其用扩容后的数组替代。
    image.png|600
  • calculateCapacity() 的作用仅仅在于,检查当前操作是否是第一次添加数据。因为第一次添加元素,扩容机制应该将其扩容到 10(除非要添加的元素本身需要的容量大于 10)。
  • 而对于非第一次添加的元素,其所需容量依旧是传进来的参数
    image.png|650
    image.png|700
  • 那么根据判断,此次显然是第一次添加元素,数组为空数组,且所需容量 var1=1,<10。那么此时 var0=10,这就确定了最终数组所需要的容量大小。作为参数传递给 ensureExplicitCapacity() 中。
    image.png|650
  • modCount 为当前集合被修改的次数。需要自增。
  • 最后进行检查:目前数组的容量(elementData.length)是否满足所需要的容量大小(var1)呢?
  • 显然,目前的数组大小为 0,而我们所需要的容量为 10。所以需要扩容。进入到 grow() 中,进行真正的扩容操作。
    image.png|600
  • 所需的容量大小为 var1=10,作为参数传递进来。
  • var2=数组目前的容量==(var2=0)==
  • var3=扩容为当前数组容量的 1.5 倍,不过在初次扩容中,此次操作不起作用==(var3=0)==
  • 判断扩容后的容量大小 var3 是否满足,所需的大小 var1,不满足则依照 var1。(var3=10)
  • 判断扩容后的容量是否在数组的取值范围内。
  • Arrays.copyOf():创建一个指定长度的数组==(10)==的数组,并将原数组中的数据拷贝至该数组,并赋值给 elementData
  • 至此,数组的扩容完成(elementData.length 从 0 扩容到 10)回到 add 的主逻辑中:
    image.png|600
  • 添加元素“11”添加到数组 elementData[0]中,并且 size=1;

第二次添加元素“12”(不用扩容)

  • 将 int 数据进行装箱
  • 添加这个数据“12”,要保证数组的长度至少为当前元素数+1。(size+1=2)
  • ensureCapacityInternal() 的作用就是检查数组是否大于等于 2(够不够此次添加所需的容量)。如果不够,则扩容,更改 elementData ,将其用扩容后的数组替代。
    image.png|600
  • 此时由于不是第一次添加,数组长度不为 0,所以 calculateCapacity() 执行后返回 2
    image.png|600
    image.png|700
  • 集合修改次数+1
  • 当前数组长度==(elementData.length=10)满足所需长度(var1=2)==,所以不需要扩容。
    image.png|550
  • 回到主逻辑中:
    image.png|600
  • elementData[1]存放 var1。size 变为 2。

观察第十一次添加元素(第二次扩容)

  • 此时数组容量为 elementData.length=10,所需容量大小为 var1=11,在这一步时,容量不够,所以需要进行扩容,进入 grow()
    image.png|650
  • var2=10,var3=15(扩容 1.5 倍)
    image.png|600

同理,后面每一次添加和扩容都与以上的步骤一致。

指定初始容量

  • 与未指定的区别在于,调用的是带参的构造器。
  • 指定了初始容量 var1,则创建一个初始容量为 var1 的数组。如果本身为 0,就仍旧赋值为空数组(与无参的一致)
  • 在之后的扩容中,依旧是按照 1.5 倍扩容。
  • 例如指定初始容量为 8,则初次扩容为 8->12
    image.png

相关文章:

  • docker3-容器与镜像命令
  • 【算法】动态规划
  • oracle11.2.0.4 RAC 保姆级静默安装(二) DB数据库软件
  • 零信任身份安全的基本原则
  • leetCode求两数之和(第一题)
  • Qt6.8.2中JavaScript调用WebAssembly的js文件<1>
  • linux-Openmanus本地部署-AI-Agent初探
  • 【农业大数据处理与应用】实验二 随机森林算法与LSTM循环神经网络
  • Linux文件系统管理
  • Spark;scp命令,rsync命令,ssh命令
  • 技术解析与实战指南:MySQL性能优化与高效数据库迁移工具推荐
  • 深度剖析《数理化学习》期刊:数理化教育领域的学术明珠
  • JAVA使用jar包外前端
  • 统一 Elastic 向量数据库与 LLM 功能,实现智能查询
  • 文档在线协同工具ONLYOFFICE教程:如何使用宏对 PDF 表单中的特定字段执行计算
  • 设计模式之美
  • LeetCode-移动零
  • 如何配置Socks5代理
  • 56.HarmonyOS NEXT 登录模块开发教程(十):总结与展望
  • 游戏引擎学习第156天
  • 贵阳网络网站建设/免费建自己的网址
  • 昆明做网站猫咪科技/杭州seo中心
  • 网站建设968/宁德市医院
  • wordpress免费企业资讯主题/百度关键词优化工具
  • 哪家做网站最好/网站流量统计分析报告
  • 学做网站论坛/seo优化便宜