首页 > 编程语言 > 详细

JavaSE合集五_ArrayList扩容机制

时间:2021-04-03 12:58:23      阅读:15      评论:0      收藏:0      [点我收藏+]

ArrayList扩容机制——源码探究

    public static void main(String[] args) {
        Collection col = new ArrayList();

        for (int i = 0; i <= 10; i++) {
            col.add(i);
        }
    }


//对上面这段代码进行调试   来探究扩容机制。

    /**
     * 首先进入一个空参构造器,会给ArrayList维护的数组elementData[]
     * 分配一个空间DEFAULTCAPACITY_EMPTY_ELEMENTDATA(默认容量为空的数组),但是没有分配容量大小。
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * 然后进行添加,添加之前会调用ensureCapacityInternal方法确实是否扩容
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

    /**
     * ensureCapacityInternal中接收到数组需要的最小容量minCapacity   即已有的数据长度+需要新增的数据长度
     * 首先调用calculateCapacity,看数组是不是空参构造器构造的空数组
     */
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    /**
     * 此方法判断数组是不是空参构造器构造的空数组,若是就看最少需要容量与默认第一次扩容的容量(10)谁大
     * 扩多的那个  不然不能满足需求
     * 
     * 在第二次扩容时,elementData不是空了  直接就返回需要的最小容量
     * 此方法我觉得作用就是检验elementData是不是空数组,若是空数组,就计算第一次数组的容量该赋多少
     */
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);//DEFAULT_CAPACITY == 10
        }
        return minCapacity;
    }

    /**
     * 这里接收到的minCapacity才是真正的最小容量所需,也是真正判断是否需要扩容的地方
     * 如果最小需要容量,大于了数组长度  则调用grow方法扩容
     */
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//是一个transient修饰的变量,不可序列化,作用就是记录检查扩容的次数,以防止多线程同时操作。

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

    /**
     * 真正扩容的地方,
     * 先获取数组长度,然后将数组长度赋给oldCapacity,使其变为1.5倍
     * 若数组长度是0,那么计算结果也是0,
     * 所以就会先将newCapacity - minCapacity比较防止扩容0个
     * Arrays.copyOf()会将elementData的数据之前的保留下来,之后完成扩容
     * 之后在add()中就添加数据  elementData[size++] = e;
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        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);
    }


    /**
     * 若调用带初始化大小的有参构造器
     * 若初始化大小为0  就会赋容量为空的数组对象,接下来和无参构造一样的添加等
     * 若初始化大小大于0   那么就会直接分配一个这么大的空数组对象
     * 若初始化大小小于0   那么就会抛出异常
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

因此可以得出结论:

  1. ArrayList中维护了一个Object类型的数组elementData;[debug 看源码]transient Object[] elementData;
  2. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍;
  3. 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。

JavaSE合集五_ArrayList扩容机制

原文:https://www.cnblogs.com/jtStudy/p/14613334.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!