简介
说明
本文介绍Java的ArrayList是如何进行扩容的。即:扩容的机制。
重要大小
类 | 初始大小 | 扩容倍数 | 底层实现 | 是否线程安全 | 同步方式 |
ArrayList | 10 | 1.5倍 | Object数组 | 线程不安全 | 无 |
Vector | 10 | 2倍 | Object数组 | 线程安全 | synchronized |
ArrayList在添加元素时实际容量如果不够了,就会扩容,没有HashMap那种加载因子的概念。(也可以理解为加载因子是1)。
下边介绍ArrayList的扩容机制。
扩容机制
1. new一个ArrayList对象
直接new 一个ArrayList对象时(未指定初始容量大小)是一个空的数组,容量大小为零。
public ArrayList() { // DEFAULTCAPACITY_EMPTY_ELEMENTDATA 变量为一个空的数组 // private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
2. 调用add()方法
当第一次调用ArrayList对象的add方法时,分配容量大小
public boolean add(E e) { // size为ArrayList的实际数量大小而非容量大小,若未指定容量构建ArrayList对象,size为0 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
private void ensureCapacityInternal(int minCapacity) { // 如果为空数组,最小需要容量为默认容量DEFAULT_CAPACITY 也就是10 // private static final int DEFAULT_CAPACITY = 10; if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } // 调用扩容方法 ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { //protected transient int modCount = 0; modCount++; // 如果需要的最小容量大于此时的容量,调用真正的扩容方法 // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
3. 扩容
private void grow(int minCapacity) { // transient Object[] elementData; // overflow-conscious code int oldCapacity = elementData.length; // 第一次扩容1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); // 还是比需要的容量小就把需要的容量作为新的容量值 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 这里主要防止1.5倍扩容导致新容量值超过数组最大容量。 // 如果新的容量比数组最大容量还大,则比较需求容量和数组最大容量 // 如果需求容量比数组最大容量大就取整数最大值,反之取数组最大容量 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); } /** * The maximum size of array to allocate. * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
请先
!