ArrayList源码分析
ArrayList底层是数组实现的,可以做到动态增长。下面通过简单的源码分析来大致看看ArrayList的添加过程。
新建一个list 并对add()方法打上断点,debug。
add()方法如下,size一开始并未赋值 为0
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return <tt>true</tt> (as specified by {@link Collection#add}) */ public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
进入到ensureCapacityInternal()方法 此时minCapacity为1 elementData刚开始为 transient Object[] elementData的空数组
private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); }
再进入calculateCapacity()方法,此时 DEFAULTCAPACITY_EMPTY_ELEMENTDATA也是一个空数组,
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
而 DEFAULT_CAPACITY一开始默认为10
由此可见,第一次添加的时候执行 if里面的方法 返回默认长度和minCapacity的最大值也就是10;以后进入由于elementData不为空 因此直接返回minCapacity
private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; }
1 private void ensureExplicitCapacity(int minCapacity) { 2 modCount++; 3 4 // overflow-conscious code 5 if (minCapacity - elementData.length > 0) 6 grow(minCapacity); 7 }
5行此时 minCapacity为默认的10 明显大于一开始的空数组的长度 进入grow();方法 ;同时,该方法也说明只有当minCapacity大于elementData数组长度的时候开始进行扩容。
1 private void grow(int minCapacity) { 2 // overflow-conscious code 3 int oldCapacity = elementData.length; 4 int newCapacity = oldCapacity + (oldCapacity >> 1); 5 if (newCapacity - minCapacity < 0) 6 newCapacity = minCapacity; 7 if (newCapacity - MAX_ARRAY_SIZE > 0) 8 newCapacity = hugeCapacity(minCapacity); 9 // minCapacity is usually close to size, so this is a win: 10 elementData = Arrays.copyOf(elementData, newCapacity); 11 }
第四行新的数组长度为 原数组长度加上原数组长度除以二 此时还是为0,第五行此时新容量小于minCapacity因此新容量就为minCapacity10、
然后进去第十行对数组进行复制,也就创建了一个长度为10的数组。
一路返回至add()方法 添加元素 size++
做个总结,ArrayList默认的数组为0,当第一次添加元素的时候便开始扩容为默认值10。随后如果有数组不断地添加,只有在size大于原数组长度的时候,开始扩容。扩容方法为原长度除以二再加原长度,也就是1.5倍扩容。
由于水平有限,有错误欢迎指出,一起学习。