ArrayList 扩容规则

1. ArrayList() 会使用长度为零的数组

如果是无参构造,则会将DEFAULTCAPACITY_EMPTY_ELEMENTDATA(空对象)的值复制给elementData, 再执行添加操作时,才会给数组赋值(见第四点)
在这里插入图片描述
DEFAULTCAPACITY_EMPTY_ELEMENTDATA空对象
在这里插入图片描述
追踪add方法可到这儿

//1 . add(E e)
 public boolean add(E e) {
    
    
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
   //2.ensureCapacityInternal
   private void ensureCapacityInternal(int minCapacity) {
    
    
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    //3.calculateCapacity
 private static int calculateCapacity(Object[] elementData, int minCapacity) {
    
    
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    
    
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

2. ArrayList(int initialCapacity) 会使用指定容量的数组

在这里插入图片描述

3. public ArrayList(Collection<? extends E> c) 会使用 c 的大小作为数组容量

在这里插入图片描述

4. add(Object o) 首次扩容为 10,再次扩容为上次容量的 1.5 倍

在这里插入图片描述在这里插入图片描述// private static final int DEFAULT_CAPACITY = 10;
在这里插入图片描述
// 如果是扩容,则扩容老数据组的1.5倍
在这里插入图片描述
在这里插入图片描述

5. addAll(Collection c) 没有元素时,扩容为 Math.max(10, 实际元素个数),有元素时为 Math.max(原容量 1.5 倍, 实际元素个数)

在这里插入图片描述

后面主要还是扩容这一段代码:

注: 有元素时为什么为 是Math.max(原容量 1.5 倍, 实际元素个数),主要是这里可能发生一次扩容,如果原数组长度+新添加的c的长度大于原容量,则会扩容一次成为原容量的1.5倍;如果原数组长度+新添加的c的长度不超过原容量,则不会扩容

  private static int calculateCapacity(Object[] elementData, int minCapacity) {
    
    
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    
    
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    private void ensureCapacityInternal(int minCapacity) {
    
    
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private void ensureExplicitCapacity(int minCapacity) {
    
    
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    ```

测试代码:
···java
public class ArrayListAddCapacity {
    
    

    public static void main(String[] args) {
    
    
      // System.out.println(arrayListGrowRule(30));
       // testAddAllGrowEmpty();
        testAddAllGrowNotEmpty();
    }

    /**
     * 空构造方法
     * @param n
     * @return
     */
    private static List<Integer> arrayListGrowRule(int n) {
    
    
        List<Integer> list = new ArrayList<>();
        int init = 0;
        list.add(init);
        if (n >= 1) {
    
    
            init = 10;
            list.add(init);
        }
        for (int i = 1; i < n; i++) {
    
    
            init += (init) >> 1;
            list.add(init);
        }
        return list;
    }

    /**
     * addAll(Collection c)  没有元素时
     */
    private static void testAddAllGrowEmpty() {
    
    
        ArrayList<Integer> list = new ArrayList<>();
        list.addAll(Arrays.asList(1, 2, 3));
        list.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
        System.out.println(length(list));
    }

    /**
     * addAll(Collection c)  有元素时
     */
    private static void testAddAllGrowNotEmpty() {
    
    
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < 1; i++) {
    
    
            list.add(i);
        }
        list.addAll(Arrays.asList(1, 2, 3));
        System.out.println(length(list));
        list.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7));
        System.out.println(length(list));
    }
	/**
	反射获取数组长度
	*/
    public static int length(ArrayList<Integer> list) {
    
    
        try {
    
    
            Field field = ArrayList.class.getDeclaredField("elementData");
            field.setAccessible(true);
            return ((Object[]) field.get(list)).length;
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return 0;
        }
    }

}

来源: https://www.bilibili.com/video/BV15b4y117RJ?p=32

猜你喜欢

转载自blog.csdn.net/loveyour_1314/article/details/120755981