【数组】- ArrayList自动扩容机制

注意:数组

不一样的JDK版本的扩容机制可能有差别 实验环境:JDK1.8函数

扩容机制性能

当向ArrayList中添加元素的时候,ArrayList若是要知足新元素的存储超过ArrayList存储新元素前的存储能力,ArrayList会加强自身的存储能力,已达到存储新元素的要求this

ArrayList:本质经过内部维护的数组对象进行数据存储code

①:分析ArrayList的add(E)方法对象

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

分析:add方法首先经过ensureCapacityInternal()方法确保当前ArrayList维护的数组具备存储新元素的能力,通过处理以后将元素存储在数组elementData的尾部 elementData:ArrayList真正用于存储元素的数组ci

②:分析ensureCapacityInternal方法element

private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }

分析:ensureCapacityInternal判断ArrayList默认的元素存储数据是否为空,为空则设置最小要求的存储能力为必要存储的元素和默认存储元素个数的两个数据之间的最大值,而后调用ensureExplicitCapacity方法实现这种最低要求的存储能力rem

注意:ArrayList的存储空间并非须要一个建立一个,而是分阶段性的建立,通常会预留存储空间。 例如,若是ArrayList须要存储10个元素,刚好ArrayList只能存储6个元素,剩余4个元素没法存储,ArrayList可能会一次性扩展10个元素,这种ArrayList就有20个元素的存储能力,在存储能力范围内,下次再存放元素,就不须要再次扩容工作流

③:分析ensureExplicitCapacity方法:

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

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

分析:若是最低要求的存储能力>ArrayList已有的存储能力,这就表示ArrayList的存储能力不足,所以须要调用 grow();方法进行扩容 ④:分析grow()方法

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        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扩容的时候,首先会设置新的存储能力为原来的1.5倍

int newCapacity = oldCapacity + (oldCapacity >> 1);

若是扩容以后仍是不能知足要求则MAX_ARRAY_SIZE比较,求取最大值, 若是MAX_ARRAY_SIZE大小的能力仍是不能知足则经过hugeCapacity()方法获取ArrayList能容许的最大值:

private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

从hugeCapacity方法看出,ArrayList最大的存储能力:存储元素的个数为整型的范围。 肯定ArrayList扩容以后最新的可存储元素个数时,调用 elementData = Arrays.copyOf(elementData, newCapacity); 实现elementData数组的扩容,整个流程就是ArrayList的自动扩容机制工做流程

扩展: ArrayList的自动扩容机制底层借助于System实现

public static native void arraycopy
  (Object src,  int  srcPos,
   Object dest, int destPos,
   int length);

arraycopy标识为native意味JDK的本地库,不可避免的会进行IO操做,若是频繁的对ArrayList进行扩容,绝不疑问会下降ArrayList的使用性能,所以当咱们肯定添加元素的个数的时候,咱们能够事先知道并指定ArrayList的可存储元素的个数,这样当咱们向ArrayList中加入元素的时候,就能够避免ArrayList的自动扩容,从而提升ArrayList的性能

ArrayList含参构造函数:初始化时指定存储元素的能力:

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);                                               
        }
    }
相关文章
相关标签/搜索