Java ArrayLiat集合底层原理

64 阅读2分钟

ArrayLiat集合底层原理

ArrayList定义在Java.util包下

ArrayList底层是数组结构的

  • 利用空参创建的集合,在底层创建一个默认长度为0的数组,数组名叫elementData,与此同时在底层还有一个成员变量叫size,用来记录元素个数
  • 添加第一个元素时,底层会创建一个新的长度为10的数组,数组名叫elementData,将元素放到0索引的位置,同时size++
    • size这个变量有两层含义
      • 元素个数
      • 下次存入位置
  • 存满时,会扩容1.5倍,将数据拷贝到新数组中
  • 再次存满时,再扩容1.5倍
  • 如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准
//这玩意就是一个空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

//底层就是一个叫elementData的数组
transient Object[] elementData;

private int size;

//空参构造,将空数组传给elementData
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

//添加元素
public boolean add(E e) {
    modCount++;
    add(e, elementData, size);//调用了重载的add方法
    return true;
}

//重载的add方法,private修饰,只能在类中调用
//传入的参数分别为 要添加的元素、集合底层的名字、集合的长度/当前元素应存入的位置
private void add(E e, Object[] elementData, int s) {
    if (s == elementData.length) {  //判断数组是否存满
        elementData = grow();  //若存满,调用grow方法扩容
    }
    elementData[s] = e;  //添加元素到数组中
    size = s + 1;  //size++
}

//add方法中的调用grow方法
private Object[] grow {
    return grow(size + 1);  //再次调用重载的grow方法进行扩容
}

//重载的grow方法
private Object[] grow(int minCapacity) {  //将需要扩容后的数组最小长度作为参数传入方法
    int oldCapacity = elementData.length; //记录原数组的长度
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {  //如果原数组长度不为0或不为空
        //调用了ArraySupport.newLength方法计算数组的最新长度
        //传入的参数分别为 原数组的长度、需要扩容的最小长度、默认扩容长度(这里右移一位就是除以2)
        int newCapacity = ArraySupport.newLength(oldCapacity, minCapacity - oldCapacity, oldCapacity >> 1);
        return elementData = Arrays.copyOf(elementData, newCapacity);  //调用Arrays.copyOf方法拷贝数组并返回
    } else {  //如果原数组长度为0或为空
        return elementData = new Object[Math.max(DEFAULT_ minCapacity)];  //创建一个新的数组并返回,数组的长度为10(常量)和需要扩容后的数组最小长度之间的最大值
    }
}

private static final int DEFAULT_CAPACITY = 10;


//ArraySupport.newLength方法 计算数组的最新长度
//传入的参数分别为 原数组的长度、需要扩容的最小长度、默认扩容长度(原数组长度的一半)
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
    //计算数组的最新长度  原长度加上 需要扩容的最小长度和默认扩容长度之间的最大值
    int prefLength = oldLength + Math.max(minGrowth, prefGrowth);
    //如果这个最新长度大于0且不超过数组最大长度(21亿多)
    if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
        return prefLength; //返回
    } else {
        return hugeLength(oldLength, minGrowth);
    }
}