ArrayList源码解析(面试必问)

ArrayList源码解析

属性分析:

默认初始容量
private static final int DEFAULT_CAPACITY = 10;
ArrayList空实例共享一个空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
用于默认大小的空实例的共享空数组实例。
将其与EMPTY_ELEMENTDATA区分开来,用来了解当添加第一个元素的时候需要创建多大的空间

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
真正存储ArrayList中元素的数组
transient Object[] elementData;
ArrayList中的元素个数
private int size;

构造方法

无参构造

public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

有参构造

在这里插入图片描述

普通方法

添加方法
首先,我们来看看这个add方法:

 public boolean add(E e) {
//确认list容量,看看是否需要容量增加
 ensureCapacityInternal(size + 1); // Increments modCount!!
//将元素放到已有元素的下一个位置
 elementData[size++] = e;
 return true;
 }

接下来我们来看看这个小容量(+1)是否满足我们的需求:

 // 获取到满足需求的最小容量
 private void ensureCapacityInternal(int minCapacity) {
 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
 }

先将这个容量值传入calculateCapacity方法,计算容量

 private static int calculateCapacity(Object[] elementData, int minCapacity) {
 // elementData是空列表
 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
 // 扩容数组到DEFAULT_CAPACITY(10)
 return Math.max(DEFAULT_CAPACITY, minCapacity);
 }
 // return size+1
 return minCapacity;
 }

然后判断是否需要扩容,如果需要扩容,就调用grow()方法,进行扩容


 // 判断是否需要扩容
 private void ensureExplicitCapacity(int minCapacity) {
 modCount++;
 if (minCapacity - elementData.length > 0)
 //调用grow方法进行真正地扩容
 grow(minCapacity);
 }

步骤解析:

1,当添加第1个元素到 ArrayList 中时,minCapacity 为size+1=1,elementData还是空的list,elementData.length=0 ,所有会执行return Math.max(DEFAULT_CAPACITY, minCapacity) 返回值为DEFAULT_CAPACITY,也就是10 ;
minCapacity变为10。此时,minCapacity - elementData.length > 0成立,所以会进入 grow(minCapacity) 方法真正扩容。
2,当添加第2个元素时,minCapacity 为 size+1 =2,由于elementData.length在添加第一个元素后已经扩容成10了。此时,minCapacity - elementData.length > 0 不成立,不会执行grow(minCapacity) 方法,即不会扩容。
3,添加第 3、4、5…到第10个元素时,依然不会扩容,数组容量还是为10。
直到添加第11个元素,minCapacity - elementData.length > 0 成立,执行grow 方法进行扩容。

所以,接下来看看grow()是怎么实现的~

private void grow(int minCapacity) {//11
        // oldCapacity为旧容量
        int oldCapacity = elementData.length;//10
        // 位移运算符比普通运算符的运算快很多。>>表示将oldCapacity右移一位,(oldCapacity >> 1)相当于oldCapacity /2
        // 将新容量更新为旧容量的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 若新容量还是小于最小需求容量
        if (newCapacity - minCapacity < 0)
            // 直接最小需求容量当作数组的新容量
            newCapacity = minCapacity;
       //如果minCapacity大于最大容量,则新容量则为`Integer.MAX_VALUE`,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 `Integer.MAX_VALUE - 8`。
        // 新容量大于MAX_ARRAY_SIZE,
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            // 执行hugeCapacity()方法
            newCapacity = hugeCapacity(minCapacity);
            elementData = Arrays.copyOf(elementData, newCapacity);
    }

ArrayList创建空实例以及扩容总结:

1,创建无参构造的ArrayList,默认创建的是空数组,长度为0
2,当往这个ArrayList对象中,放入第一个元素之后,数组扩容,扩容到默认长度10
3,当放入到第11个元素的时候,数组继续扩容,扩容到原数组长度的1.5倍,即将10扩容到15

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值