一些关键变量
从这里 可以看出ArrayList内部和String一样也是用的数组来实现的
首先看构造方法
//就是初始化了一个空数组
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
看一下常用的方法
1:add
public boolean add(E e) {
//首先确保本地容量,以免出现越界
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//这里的minCapacity大小事当前数组逻辑大小再加1,毕竟我们在add数据当然要加1
//所以第一次调用的话minCapacity就等于1
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//第一次调用的时候elementData还是个空数组,minCapicity也只是1,DEFAULT_CAPACITY是一个静态常量等于10
//所以这段代码的逻辑就是如果是空数组就返回DEFAULT_CAPACITY和minCapacity的最大值,数组不为空的话直接返回minCapacity
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 根据上面的分析这里的minCapacity要么是10要么是ArrayList逻辑长度再加1,第一次add那么这里if肯定是大于0的
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {//第一次add这里是10
// overflow-conscious code
int oldCapacity = elementData.length;
//这里是数组的扩容,第一次的长度为0 0的右移还是0所以根据下面的逻辑ArrayList的初试大小是10,之所以我们调用size获取的是0,是因为返回的是逻辑长度并不是返回的数组的长度
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:
//这里和string一样也是用到了数组的拷贝
elementData = Arrays.copyOf(elementData, newCapacity);
}
以上就是ArrayList的初始化流程和扩容流程
2:remove
public E remove(int index) {
rangeCheck(index);//首先确保没有数组越界的问题
modCount++;
E oldValue = elementData(index);//取出对应下标的字符
//这里还是用到了数组的拷贝只不过被拷贝的数组和目标数组是同一个,准确的说是数组的移动,比如现在有十个数据删除第五个就是把后面的数据全部向前拷贝一次,这样其实还是十个数据只是最后两个的数据是一样的所有这里会把数组的最后一个数组置空 --size这样逻辑长度size变了置空后也方便jvm对这个对象回收
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}