“`” ArrayList是List接口的实现类,它是支持根据需要而动态增长的数组。java中标准数组是定长的,在数组被创建之后,它们不能被加长或缩短。这就意味着在创建数组时需要知道数组的所需长度,但有时我们需要动态程序中获取数组长度。ArrayList就是为此而生的。
<span style=""font-size: 1rem;""> 因此,了解它的扩容机制对使用它尤为重要。</span><br>
<span style=""font-size: 1rem;""> ArrayList扩容发生在add()方法调用的时候,下面是add()方法的源码:</span><br></p>
<pre><span style=""font-size: 1rem;""> public boolean add(E e) {<br></span> //扩容<br> ensureCapacityInternal(size + 1); // Increments modCount!!<br> elementData[size++] = e;<br> return true;<br> }</pre>
根据意思可以看出ensureCapacityInternal()是用来扩容的,形参为最小扩容量,进入此方法后:
<br>
<pre>private void ensureCapacityInternal(int minCapacity) {<br> ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));<br>}</pre>
<br>
通过方法calculateCapacity(elementData, minCapacity)获取:
<pre><span style=""font-size: 1rem;""> private static int calculateCapacity(Object[] elementData, int minCapacity) {<br></span> //如果传入的是个空数组则最小容量取默认容量与minCapacity之间的最大值<br> if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {<br> return Math.max(DEFAULT_CAPACITY, minCapacity);<br> }<br> return minCapacity;<br> }</pre>
<br>
ensureExplicitCapacity方法可以判断是否需要扩容:
<br>
<pre> private void ensureExplicitCapacity(int minCapacity) {<br> modCount++;<br> <br> // 如果最小需要空间比elementData的内存空间要大,则需要扩容<br> if (minCapacity – elementData.length > 0)<br> //扩容<br> grow(minCapacity);<br> }</pre>
<br>
接下来重点来了,ArrayList扩容的关键方法grow():
<pre><span style=""font-size: 1rem;""> private void grow(int minCapacity) {<br></span> // 获取到ArrayList中elementData数组的内存空间长度<br> int oldCapacity = elementData.length;<br> // 扩容至原来的1.5倍<br> int newCapacity = oldCapacity + (oldCapacity >> 1);<br> // 再判断一下新数组的容量够不够,够了就直接使用这个长度创建新数组,<br> // 不够就将数组长度设置为需要的长度<br> if (newCapacity – minCapacity < 0)<br> newCapacity = minCapacity;<br> //若预设值大于默认的最大值检查是否溢出<br> if (newCapacity – MAX_ARRAY_SIZE > 0)<br> newCapacity = hugeCapacity(minCapacity);<br> // 调用Arrays.copyOf方法将elementData数组指向新的内存空间时newCapacity的连续空间<br> // 并将elementData的数据复制到新的内存空间<br> elementData = Arrays.copyOf(elementData, newCapacity);<br> }</pre>
<span style=""font-size: 1rem;""> 从此方法中我们可以清晰的看出其实<b>ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去</b>。</span>
到此扩容就基本完成了。
<pre><code> "“`
Was this helpful?
0 /
0