解析ArrayList集合底层原理

一、 ArrayList底层实现?

Object[] elementData;

 ArrayList 的底层实现是通过Object类型的数组来实现的

二、ArrayList的构造

//无参构造:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//空对象数组
   public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
   }  

private static final Object[] EMPTY_ELEMENTDATA = {};//空对象数组
//带参构造:
    ArrayList<String> list = new ArrayList<>(0);
 public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
                       //先构造数组,如果有的话,从给的开始
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

注意:这里对定义了两个常量空数组,并不是麻烦而是一种设计

  -----虽然都为空,但内存地址不一样是两个不同的数组;以便区分这是默认构造还是带参构造时给的长度为0的数组。是为了后面的判断。

三、ArrayList的add方法

//添加元素
public boolean add(E e) {
        //数组容量--确保内部容量---数组
        ensureCapacityInternal(size + 1);  //  private int size=0;//元素个数为0
        elementData[size++] = e;//数组赋值
        return true;
}

add()方法中:首先确保ArrayList的容量(判断是否需要扩容);然后将元素添加到elementData数组的指定位置;最后将集合中实际的元素个数加1。 

四、ArrayList的扩容机制

      1、 确保和计算容量

//确保容量
private void ensureCapacityInternal(int minCapacity) {//1
        //计算容量---10
        int minCapacity = calculateCapacity(elementData, minCapacity);
        ensureExplicitCapacity(minCapacity);//计算明确的容量
}
//计算容量---为无参构造的第一次而写
private static int calculateCapacity(Object[] elementData, int minCapacity ) {
        //第一次满足
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // private static final int DEFAULT_CAPACITY = 10;
            //第一次扩容的大小是10--当我们用无参构造时,

            return Math.max(DEFAULT_CAPACITY, minCapacity);//10
        }
        return minCapacity;
}

private void ensureExplicitCapacity(int minCapacity) {//10---2
        modCount++;//

        // overflow-conscious code
    //我需要的容量大于底层数组的长度
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);//保证容量---扩容
}

 实现步骤:

    1. 在add()方法中调用ensureCapacityInternal(size + 1)方法来确保最小容量。

第一次传过来elementData为{}(空数组),minCapacity为1;以后的都不为空就不进if循环,所以说calculateCapacity是为无参构造的第一次而写。当我们用无参构造时,第一次扩容的大小是10

    2.  调用了ensureExplicitCapacity方法计算出了明确所需的容量,如果大于底层数组的长度则扩。

2、扩容

private void grow(int minCapacity) {//10
        // overflow-conscious code
        int oldCapacity = elementData.length;//保存原来的长度---0
        int newCapacity = oldCapacity + (oldCapacity >> 1);//1.5倍扩容  0
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;//直接把新容量赋成最小需要的容量
        if (newCapacity - MAX_ARRAY_SIZE > 0)//2147483647-8
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
       //把原来数组中扩容,
        elementData = Arrays.copyOf(elementData, newCapacity);//10-15-22
}

实现方法:通过移位运算进行扩容,扩为原来的1.5倍。如果新的容量还是不满足需要的容量,则直接把新容量赋成最小需要的容量,如果容量过大则报异常(一般不可能).

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值