ArrayList的扩容原理

扩容:

ArrayList,如果使用有参构造函来创建,先根据指定容量创建数组,后续以1.5倍进行扩容;如果使用无参构造函数来创建,第一次添加元素,扩容到10,后续也是以1.5倍进行扩容。

源码剖析

以无参方式创建ArrayList集合
  1. public class Test1 {
        public static void main(String[] args) {
            //首先从无参的构造函数看起
            ArrayList<String> list = new ArrayList<>();
            list.add("6");
        }
    }
    
  2. ctrl点击后面的ArrayList<>();进入ArrayList类

        public ArrayList() {
            //以无参构造函数创建ArrayList集合对象,将elementData赋值为有一个内容为空Object数组
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
    //elementData和DEFAULTCAPACITY_EMPTY_ELEMENTDATA在ArrayList中无参默认构造函数中的初始值
    
    transient Object[] elementData;
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    
  3. 进入add(E e)方法

    public boolean add(E e) {
        // 在添加数据前确保又能够操作的空间,且为扩容的条件,当size为elementDate的长度时,扩容条件满足
        ensureCapacityInternal(size + 1);  
        elementData[size++] = e;
        return true;
    }
    
    private int size;//ArrayList的私有属性,初始值为0
    
  4. 进入ensureCapacityInternal(size + 1)

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    
  5. 进入calculateCapacity(elementData, minCapacity)

    //minCaoacity:1  elementData:空的Object数组
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //elementData之前被DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋过值,结果为ture
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //DEFAULT_CAPACITY = 10 ,静态常量
         return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
     //minCapacity = 10
        return minCapacity;
    }
    
  6. 进入ensureExplicitCapacity(int minCapacity)

    //minCapacity = 10
    private void ensureExplicitCapacity(int minCapacity) {
        	//记录从this对象创建以来,增删改查方法每执行一次,modCount都会++一次
         modCount++;
        	//elementData.length = 0  elementData为Object空容器数组  minCapacity = 10
         if (minCapacity - elementData.length > 0)
                //核心扩容方法
                grow(minCapacity);
    }
    
  7. 进入grow(minCapacity)

    private void grow(int minCapacity) {
        // 记录旧的容器的大小
        int oldCapacity = elementData.length;
        // 预计要扩容到的容量,为旧容器的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //如果新的容器大小小于当前容器的大小,值被当前容器大小覆盖
        if (newCapacity - minCapacity < 0)
         newCapacity = minCapacity;
        //private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
     /*
        数组有点特殊性,数组对象要额外存储数组元素长度在头部,少了这8个长度可能与此有关。
    	尝试分配大于 MAX_ARRAY_SIZE 长度的数组会导致 OOM (换句话说,超过了该虚拟机的数组长度限制)。 ,一	般用不到,就不做过多解释
    	*/
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 给elementDate扩容并将之前的值继承,大小为newCapacity.length()
        elementData = Arrays.copyOf(elementData, newCapacity);
    
  8. 返回add()

       //e 即传入的参数
       public boolean add(E e) {
           ensureCapacityInternal(size + 1);
           //执行此条语句,默认从0下标开始被e值覆盖
           elementData[size++] = e;
           return true;
       }
    
有参方式创建ArrayList集合
  1. ​ 有参方式创建arrayList集合

    public class Demo1 {
        public static void main(String[] args) {
            ArrayList<String> arrayList = new ArrayList<>(20);
            arrayList.add("张三");
        }
    }
    
  2. 进入有参方法

    //initialCapacity 传入的参数
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            //这里是new了一个Object对象数组,并非DEFAULTCAPACITY_EMPTY_ELEMENTDATA覆盖 
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            //EMPTY_ELEMENTDATA 一个内容为空Object数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
        }
    }
    
  3. 进入add(E e)方法

    public boolean add(E e) {
        //private int size;-------ArrayList的私有属性,初始值为0
        ensureCapacityInternal(size + 1);
        elementData[size++] = e;
        return true;
    }
    
  4. 进入ensureCapacityInternal(size + 1)

    //minCapacity:1
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    
  5. 进入calculateCapacity(elementData, minCapacity),有返回

    //minCaoacity:1  elementData:空的Object数组 
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //elementDate的地址是new的或被EMPTY_ELEMENTDATA这个空的Object[]覆盖,结果为false
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //mincapacity = 1
        return minCapacity;
    }
    
  6. 进入ensureExplicitCapacity(int minCapacity)

    //minCapacity = 1
    private void ensureExplicitCapacity(int minCapacity) {
        //记录从this对象创建以来,增删改查方法每执行一次,modCount都会++一次
        modCount++;
        //elementData.length = 20,不进入grow()方法
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    
  7. 返回add()

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);
        //执行此条语句,默认从0下标开始被e值覆盖
        elementData[size++] = e;
        return true;
    }
    
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值