首页 > 编程语言 >20220929-ArrayList扩容机制源码分析

20220929-ArrayList扩容机制源码分析

时间:2022-09-29 22:13:19浏览次数:59  
标签:20220929 ArrayList elementData int minCapacity null 源码 size

示例代码

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,elementData,int,minCapacity,null,源码,size
From: https://www.cnblogs.com/zhanghuaze/p/16743281.html

相关文章

  • Spring源码-InstantiationAwareBeanPostProcessor
    InstantiationAwareBeanPostProcessor继承了BeanPostProcessor接口,扩展了BeanPostProcessor的功能。publicinterfaceBeanPostProcessor{/**调用init方法的前置处理......
  • 20220929
    20220929(中)t1智力大冲浪传送门思路​ 非常明显的贪心,能尽可能的少扣钱就少扣钱,即将每个游戏按其价值从大到小排序。那么考虑如何在该基础上加入时间的情况下贪心。......
  • php源码安装
    参考:https://www.sunanzhi.com/archives/27/ 安装1、到官网获取下载地址 https://www.php.net/downloads2、下载并解压cd/home/install/php74wgethttps://www......
  • Spring源码学习:day2
    前言:我还是太懒了,连截图都懒得粘贴,故直接用书上说的话的截图吧。代码的编写过程都是应该有一个入口的,所有的代码最终都是为了那个入口更加方便更加简单而产生的。......
  • Spring 源码学习:day1
    前言:最近也不知道该忙些什么样的事情。便随便看看源码算了。正文:(1)在网上下载Spring的源码:可以采用git方式下载 https://github.com/spring-projects/s......
  • python人工智能项目实战,PDF+源码
    机器学习AI算法工程 公众号:datayx《python人工智能项目IntelligentProjectsUsingPython》实施机器学习和深度学习方法,使用Python构建智能,认知AI项目主要特点帮助您掌......
  • 互联网医院系统源码的发展趋势||数字医疗搭建
    疫情当下,为了缓解患者就医难的问题,有很多医院建立了互联网医院。不但可以利用图文,视频等方式为患者提供咨询类的医疗服务,也可以线上诊断,开处方,检查检验,结合线上线下安排进一......
  • 国庆微信换头像小程序实现原理及源码
    又准备到国庆了,很多人又要开始换头像了,每到节日微信小程序换头像小程序流量都要大涨。在网上经常看到很多国庆微信小程序换头像的,比如国庆节,圣诞节等节日头像框,一键换头像,......
  • HashMap源码,看我这篇就够了
    HashMap源码深度剖析*HashMap底层数据结构(为什么引入红黑树、存储数据的过程、哈希碰撞相关问题)*HashMap成员变量(初始化容量是多少、负载因子、数组长度为什么是2......
  • Optional源码解析与实践
    1导读NullPointerException在开发过程中经常遇到,稍有不慎小BUG就出现了,如果避免这个问题呢,Optional就是专门解决这个问题的类,那么Optional如何使用呢?让我们一起探索一下......