所谓动态数组的扩容,就是包装下面这个api 。
Arrays.copyOf(elementData, newCapacity);
没有耐心的小伙伴直接跳转到 grow(minCapacity) 目录处
运用:
1 Arrays.copyOf(elementData, newCapacity); //扩容数组的api
2 System.arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length); //复制数组的api
import java.util.Arrays;
public class ArrayDemo {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = Arrays.copyOf(arr1, 5);
int[] arr3 = Arrays.copyOf(arr1, 10);
for(int i = 0; i < arr2.length; i++)
System.out.print("arr2:"+arr2[i] + " ");
System.out.println();
for(int i = 0; i < arr3.length; i++)
System.out.print("arr3:"+arr3[i] + " ");
}
}
运行结果:
arr2:1 2 3 4 5
arr3:1 2 3 4 5 0 0 0 0 0
可见扩容后的数组 补充了几个零,如果数组是对象,应该是补充几个null
参数说明:
src:源对象
srcPos:源数组中的起始位置
dest:目标数组对象
destPos:目标数据中的起始位置
length:要拷贝的数组元素的数量
简单说:
我要复制一个名字为src 的数组,
从src 数组下标为srcPos 的位置开始复制,
复制的个数是 length ,
复制的内容写到哪里 dest 数组中!
从dest 数组的的destPos 下标位置开始复制!
add(E e):添加一个元素到列表的末尾。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保数组大小够不是否,需要扩容不。
/*1 elementData 是Arraylist中存放元素的真正数组,size是当前数组中存了几个元素,而不是数组的长度!!!
*2 把添加的元素放入数组中已存入元素个数的+1位置!
*/
elementData[size++] = e;
return true;
}
记住size+1 代表加入一个元素后当前总元素的数量 很重要!!!!
private void ensureCapacityInternal(int minCapacity) {
//如果new ArrayList() 这样的实例对象,则ArrayList大小就是DEFAULT_CAPACITY--> 10大小
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//确定是否需要扩容,下一步进入
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 如果小存储的的总元素个数大于当前数组的长度,则扩容执行grow(minCapacity)
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//表示扩容一半,>>1 代表右移一位,在数学上就等同于除2,所以本身长度 oldCapactiy+自身一半, 这是扩容后的长度。
int newCapacity = oldCapacity + (oldCapacity >> 1);
//扩容前有两个情况需要注意下:
//情况1 如果扩容后的长度还是小于当前需要存入的个数minCapacity ,为扩容的大小
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//情况2 如果扩容后的长度,大于ArrayList 类中规定的最大长度,处理情况,暂时不看
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//程序走到这里就代表老老实实的扩容了,怎么样看到Arrays.copyOf() 很熟悉了吧
elementData = Arrays.copyOf(elementData, newCapacity);
}
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());//点击下一步
}
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
/*下边三元表达式,代码看起来很恶心,表达的意思是:要被复制的目标是不是Object[] 类型的
*如果是重新建一个Object[newLength] 数组,记着newLength 传递的是我们需要扩容数组的大小!!
*如果不是则把目标包装成一个数组,大小也是newLength
*最终目的就是保证传入给System.arraycopy() 方法中参数"copy" 的值是一个我们扩容后的新数组
*/
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
//眼熟吧!!!上面例子中有解释
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
如果删除23 这个数字,要把位置在7,8,9上的元素移动到6,7,8的位置上!
所以源码分析
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
//复制的个数
int numMoved = size - index - 1;//删除23,则后面的元素的位置index 7 8 9,所以需要3个
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);//numMoved代表需要复制几个!
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
更多记录请看: