码迷,mamicode.com
首页 > 其他好文 > 详细

ArrayList的扩容机制

时间:2019-03-06 01:18:24      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:ble   copy   pac   aci   list   declared   capacity   ali   random   

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
        // 第2次调用add()方法后,调用ensureCapacityInternal(2),此时elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA,所以minCapacity=2
        // 第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);
    }
}

 

ArrayList的扩容机制

标签:ble   copy   pac   aci   list   declared   capacity   ali   random   

原文地址:https://www.cnblogs.com/xy-ouyang/p/10480757.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!