木心

毕竟几人真得鹿,不知终日梦为鱼

导航

ArrayList的扩容机制

1、案例1

public class Demo1 {
    public static void main(String[] args) throws Exception {
        // Vector空参构造:容量为10
        Vector<Integer> vector = new Vector<>();
        System.out.println("vector.capacity(): " + vector.capacity()); // 10
        System.out.println("=== 分割线 ===");

        ArrayList<Integer> list = new ArrayList<>();
        System.out.println("list元素个数: " + list.size()); // 0
        System.out.println("list的容量: " + getCapacity(list)); // 0

        // 手动设置list集合的容量,因为9<DEFAULT_CAPACITY,所以不扩容
        list.ensureCapacity(9);
        System.out.println("list元素个数: " + list.size()); // 0
        System.out.println("list的容量: " + getCapacity(list)); // 0

        // 手动设置list集合的容量,因为11>DEFAULT_CAPACITY,所以扩容
        list.ensureCapacity(11);
        System.out.println("list元素个数: " + list.size()); // 0
        System.out.println("list的容量: " + getCapacity(list)); // 11
    }

    // 使用反射获取ArrayList集合的私有字段elementData,
    // elementData是一个Object数组,是ArrayList的底层实现;elementData数组的长度即为集合的容量
    public static Integer getCapacity(ArrayList<?> list) throws Exception {
        Field field;
        field = list.getClass().getDeclaredField("elementData");
        field.setAccessible(true);
        Object[] objArray = (Object[]) field.get(list);
        return objArray.length;
    }
}

 

2、案例2

  1)调用ArrayList空参构造创建集合,此时集合容量为0;

  2)添加第1个元素后,集合容量扩为10;

  3)当添加第11个后,集合容量扩为15(容量扩充为原来的1.5倍);

public class Demo2 {
    public static void main(String[] args) throws Exception {
        // Vector空参构造:容量为10
        Vector<Integer> vector = new Vector<>();
        System.out.println("vector.capacity(): " + vector.capacity()); // 10
        System.out.println("=== 分割线 ===");

        ArrayList<Integer> list = new ArrayList<>();
        System.out.println("list元素个数: " + list.size()); // 0
        System.out.println("list的容量: " + getCapacity(list)); // 0

        list.add(0); // 第一次添加,list集合扩容至10
        System.out.println("list元素个数: " + list.size()); // 1
        System.out.println("list的容量: " + getCapacity(list)); // 10

        // 再添加9个元素,塞满集合
        for (int i = 1; i < 10; i++) {
            list.add(i);
        }
        System.out.println("list元素个数: " + list.size()); // 10
        System.out.println("list的容量: " + getCapacity(list)); // 10

        // 再添加一个元素(第11次添加)
        list.add(10);
        System.out.println("list元素个数: " + list.size()); // 11
        System.out.println("list的容量: " + getCapacity(list)); // 15
    }

    // 使用反射获取ArrayList集合的私有字段elementData,
    // elementData是一个Object数组,是ArrayList的底层实现;elementData数组的长度即为集合的容量
    public static Integer getCapacity(ArrayList<?> list) throws Exception {
        Field field;
        field = list.getClass().getDeclaredField("elementData");
        field.setAccessible(true);
        Object[] objArray = (Object[]) field.get(list);
        return objArray.length;
    }
}

 

3、ArrayList的源码(jdk1.8.0_111)

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    private static final int DEFAULT_CAPACITY = 10;
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);
        elementData[size++] = e;
        return true;
    }
    
    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    private void ensureCapacityInternal(int minCapacity) {
        // elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA表示:集合通过空参构造创建,并且没有扩容过,容量为0
        // 第1次调用add()方法后,调用ensureCapacityInternal(1),此时elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,所以minCapacity=10// 第11次add()方法后,调用ensureCapacityInternal(11),minCapacity=11
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // DEFAULT_CAPACITY=10
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // 第11次add()方法后,minCapacity=11,elementData.length=10,达到扩容条件
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1); // 容量扩充为原来的1.5倍
        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);
    }
}

 

另外可以参考:

  1) 通过源码一步一步分析ArrayList 扩容机制

posted on 2019-03-05 23:52  wenbin_ouyang  阅读(643)  评论(0编辑  收藏  举报