示例代码

public class ArrayListSource {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(); //跳转至第一步
for (int i = 0; i < 10; i++) {
arrayList.add(i); //需要进行第一次扩容,跳转至第二步
}
for (int i = 11; i <= 15; i++) {
arrayList.add(i); //需要进行第二次扩容
}
arrayList.add(100); //需要进行第三次扩容
arrayList.add(200);
arrayList.add(300);
}
}

代码分析

第一步:

当使用new ArrayList()创建集合时,会调用ArrayList类的无参构造器,在集合内部存在一个空的elementData数组,代码如下

private static final int DEFAULT_CAPACITY = 10;  //默认容量
...
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //默认空数组
...
transient Object[] elementData; //存放Object对象的数组
...
private int size; //集合中所包含的元素,默认为0
...
protected transient int modCount = 0;
...
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //MAX_ARRAY_SIZE = 2147483639
...
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //elementData初始化为{}数组,其中size=0
}

第二步:

程序进入for循环,从i=0开始,执行arrayList.add(i)方法,进入ArrayList类中

public boolean add(E e) {  //此时:e=1
ensureCapacityInternal(size + 1); //跳转至第三步
elementData[size++] = e;
return true;
}

第三步:

执行ensureCapacityInternal(size + 1),其中size=0

private void ensureCapacityInternal(int minCapacity) {  //此时minCapacity=size+1=1,即给集合中添加1个元素,需要的最小容量是1
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); //跳转至第四步
}

第四步:

先执行ensureExplicitCapacity()中的嵌套函数calculateCapacity(elementData, minCapacity)

// elementData = {}
// minCapacity = 1
// DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}
// DEFAULT_CAPACITY = 10
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //此if语句成立
return Math.max(DEFAULT_CAPACITY, minCapacity); //返回值为10,退出函数,跳转至第五步,
}
return minCapacity;
}

第五步:

执行ensureExplicitCapacity()函数

// minCapacity = 10
// modCount默认为0,然后自加1
// elementData.length = 0
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0) //此时if语句成立
grow(minCapacity); //跳转至第六步
}

第六步:

执行grow(minCapacity)

// minCapacity = 10
// MAX_ARRAY_SIZE = 2147483639
private void grow(int minCapacity) {
int oldCapacity = elementData.length; //oldCapacity=0
int newCapacity = oldCapacity + (oldCapacity >> 1); //newCapacity=0+0/2=0
if (newCapacity - minCapacity < 0) //此if语句成立
newCapacity = minCapacity; //newCapacity = 10
if (newCapacity - MAX_ARRAY_SIZE > 0) //此if语句不成立
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
//此语句执行后,elementData = {null,null,null,null,null,null,null,null,null,null}
}

第七步:

当程序执行完第六步之后,根据方法调用步骤依次返回,直至第二步的第2条程序语句

public boolean add(E e) {//此时:e=1
ensureCapacityInternal(size + 1);
//通过以上方法,确保集合中可以存放e对象
elementData[size++] = e;//此时size=0,之后自加1;e=1
//执行之后 elementData = {1,null,null,null,null,null,null,null,null,null}
return true;
}

第八步:

在for循环中,不断执行 arrayList.add(i)方法,直到for循环结束,以上步骤介绍了ArrayList第一次默认初始化之后存放元素的步骤和扩容机制,当集合中存放的对象达到容量10时,集合需要再次进行扩容。而接下来的每次扩容的容量=原来容量*1.5,即 0 --> 10 --> 15 --> 22 --> 33...

20220929-ArrayList扩容机制源码分析的更多相关文章

  1. JAVA ArrayList集合底层源码分析

    目录 ArrayList集合 一.ArrayList的注意事项 二. ArrayList 的底层操作机制源码分析(重点,难点.) 1.JDK8.0 2.JDK11.0 ArrayList集合 一.Ar ...

  2. Android事件分发机制源码分析

    Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...

  3. ArrayList详解-源码分析

    ArrayList详解-源码分析 1. 概述 在平时的开发中,用到最多的集合应该就是ArrayList了,本篇文章将结合源代码来学习ArrayList. ArrayList是基于数组实现的集合列表 支 ...

  4. Springboot学习04-默认错误页面加载机制源码分析

    Springboot学习04-默认错误页面加载机制源码分析 前沿 希望通过本文的学习,对错误页面的加载机制有这更神的理解 正文 1-Springboot错误页面展示 2-Springboot默认错误处 ...

  5. ApplicationEvent事件机制源码分析

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

  6. 2.8.2 并发下的ArrayList,以及源码分析

    package 第二章.并发下的ArrayList; import java.util.ArrayList;import java.util.List; /** * Created by zzq on ...

  7. Android查缺补漏(View篇)--事件分发机制源码分析

    在上一篇博文中分析了事件分发的流程及规则,本篇会从源码的角度更进一步理解事件分发机制的原理,如果对事件分发规则还不太清楚的童鞋,建议先看一下上一篇博文 <Android查缺补漏(View篇)-- ...

  8. ArrayList 和 LinkedList 源码分析

    List 表示的就是线性表,是具有相同特性的数据元素的有限序列.它主要有两种存储结构,顺序存储和链式存储,分别对应着 ArrayList 和 LinkedList 的实现,接下来以 jdk7 代码为例 ...

  9. List中的ArrayList和LinkedList源码分析

    ​ List是在面试中经常会问的一点,在我们面试中知道的仅仅是List是单列集合Collection下的一个实现类, List的实现接口又有几个,一个是ArrayList,还有一个是LinkedLis ...

随机推荐

  1. vivado没用上的寄存器变量

    vivado中定义了但没用上的寄存器变量,在综合时会被移除,即没有综合出来.(如下cnt,虽然在y的过程块中用了cnt作为判断条件,但实际上cnt用了跟没用效果一样,所以综合时cnt_reg就被放弃了 ...

  2. 86开关、家电、台扇等6键6路6感应通道高抗干扰触摸IC-VK3606D,稳定性好,抗干扰能力强

    概述: VK3606D SOP16具有6个触摸按键,可用来检测外部触摸按键上人手的触摸动作.该芯片具有较高的集成度,仅需极少的外部组件便可实现触摸按键的检测.提供了6路1对1直接输出低电平有效.最长输 ...

  3. RabbitMQ细说之开篇

    前言 关于消息中间件的应用场景,小伙伴们应该都耳熟能详了吧,比如经常提到的削峰填谷.分布式事务.异步业务处理.大数据分析等等,分布式消息队列成为其中比较关键的桥梁,也就意味着小伙伴们得掌握相关技能:当 ...

  4. python subprocess相关操作

    python subprocess常用操作 1.subprocess模块的常用函数 函数 描述 subprocess.run() Python 3.5中新增的函数.执行指定的命令,等待命令执行完成后返 ...

  5. 快速体验Spring Boot了解使用、运行和打包 | SpringBoot 2.7.2学习系列

    SpringBoot 2.7.2 学习系列,本节内容快速体验Spring Boot,带大家了解它的基本使用.运行和打包. Spring Boot 基于 Spring 框架,底层离不开 IoC.AoP ...

  6. JavaWeb--Cookie与Session

    前言 Java Web 其实就是一个技术的总和,把Web看成一个容器而已主要使用JavaEE技术来实现.在加上各种中间件. 整个javaWeb阶段的内容通过实际的案例贯穿学习, 所涉及到的技术知识点会 ...

  7. 从零开始Blazor Server(10)--编辑角色

    例图 目前的样式是这样的: 其中角色在一个table里,然后可以增删改查,并且可以给指定的用户分配权限. 创建文件 首先我们在Pages/Admin目录下新建一个Role.razor.因为我们的Adm ...

  8. 一个注解搞定SpringBoot接口定制属性加解密

    前言 上个月公司另一个团队做的新项目上线后大体上运行稳定,但包括研发负责人在内的两个人在项目上线后立马就跳槽了,然后又交接给了我这个「垃圾回收人员」. 本周甲方另一个厂家的监控平台扫描到我们这个项目某 ...

  9. 基于.NetCore开发博客项目 StarBlog - (17) 自动下载文章里的外部图片

    系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...

  10. net::ERR_BLOCKED_BY_CLIENT 错误导致页面加载不出来

    AdBlock 禁止广告的插件屏蔽你的网络请求,屏蔽了一些重要的文件,导致页面加载不出来. 解决方案: 1.修改资源文件的名称,把ad替换成其他字符: 2.关闭广告拦截器: 3.广告拦截器设置白名单.