Fork me on GitHub

Java ArrayList扩容机制

  • ArrayList中维护了一个Object类型的数据,elementData
  •  transient Object[] elementData;
    
  •  //transient表示该对象不会被序列化(序列化——把Java对象转换为字节序列的过程)
    
  •   当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容为10,如果需要再次扩容,则扩容为elementData为1.5倍
    
  •  如果使用的是指定大小的构造器,则初始化elementData容量为指定大小,如果需要扩容,则直接扩容为elementData为1.5倍
    

通过下列示例来说明该机制

package gather.collection.list;

import java.util.ArrayList;
@SuppressWarnings({"all"})//抑制警告
/**
 * @Author Blueshadow
 * @Date 2021/7/20 11:00
 * @Version 1.0
 */
public class list {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();//elementData数组初始大小为0
        for (int i = 0; i < 10 ; i++) {
            list.add(i);
        }

        list.add(100);
        list.add(200);
        list.add(null);
        for (Object object : list) {
            System.out.println(object);
        }
    }
}

底层源码说明

第一次初始化,创建了一个名为elementData的Object类型的数组,该数组可以存放多种类型的数据,主要是通过包装类来实现。

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    //private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//创建Object类型数组
    //创建了一个空数组,并将数组命名为 elemenrData
    }

下一步:在执行list.add(1)时,会先进性判断,是否需要扩容,然后再执行赋值操作。

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 判断Increments modCount!!
        elementData[size++] = e;//赋值操作
        return true;
    }

下一步:判断是空,则给数组赋予一个最小容量,第一次add,最小容量为minCapacity。

private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//先确定elementData是否是一个空数组:
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//先确定最小容量minCapacity(第一次扩容为10)
        }
        ensureExplicitCapacity(minCapacity);//真正确定是否扩容
    }

下一步:进行底层的扩容。

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//记录当前集合被修改的次数

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)//如果elementDara容量不够,就调用grow方法进行扩容
            grow(minCapacity);//进行底层的扩容
    }

第一次扩容最后一步:底层按照1.5倍进行扩容


 private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//第一次oldCapacity=0
        int newCapacity = oldCapacity + (oldCapacity >> 1);//原先数组大小+原先数组大小/2
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);//elementData={},使用该方法将newCapacity赋值给elementData
    }
posted @ 2021-07-20 18:08  Blueshadow^_^  阅读(372)  评论(0编辑  收藏  举报