1、实例化ArrayList
看一下ArrayList的构造函数,有以下三种
public ArrayList(int initialCapacity)
public ArrayList()
public ArrayList(Collection c)
初始化过程中将会对elementData
这个数组对象进行初始化,这个对象里面保存的就是ArrayList里面的数据。
其中第一个和第二个两个的区别就是是否指定ArrayList的初始化容量,如果未指定或者传入的initialCapacity=0,会将elementData赋值为一个空的Object[]数组,如下图所示:
这里的EMPTY_ELEMENTDATA
和DEFAULTCAPACITY_EMPTY_ELEMENTDATA
都是一样的东西。
第三个构造函数传入一个集合类型的对象,然后将c转换为数组,通过Arrays.copyOf
这个方法,将该数组赋值到elementData
对象中。
2、部分方法
trimToSize方法
该方法整理elementData
对象,该对象由于是一个数组对象,它本身的大小是确定了的,在测试过程中,通过对ArrayList add值,会得到一个固定大小的elementData
数组(默认为10),当我们add的值的个数小于数组长度的时候,该数组里面的值形式为[11, sss, addd, null, null, null, null, null, null, null]
,调用该方法过后,该数组将移除掉null对象。其中采用的方法仍然是Arrays.copyOf
。
add方法
当为传入添加元素的位置的时候,该方法内部将执行以下代码:
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
这里写的就很明显了,添加的时候先判断当前elementData数组的长度是否大于传入的容量,如果小于就扩充elementData数组,扩充的算法为当前的长度+当前长度右移一位的长度。其中第一次添加的时候,会将默认的长度传入,这也就导致了就算ArrayList中就算只有一个对象,elementData的长度也会为10,如果想要将多余的长度去掉,则需要调用trimToSize方法。这里需要知道的是, elementData的长度是永远需要大于等于 ArrayList的个数的。
至于指定了添加位置的方法,则是调用 System.arraycopy
这个方法,在指定位置后的数组元素向后移位。
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
get,set方法
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
get,set方法相对而言很好理解,先判断index是否在范围,然后返回(设置)elementData数组里面的相应元素
remove方法
当remove传入的index的时候,只需要将数组里面的元素删除即可。
当出入对象的时候,通过遍历整个数组,找到元素索引。通过fastRemove(index)
方法进行删除。
private void fastRemove(int index) {
modCount++;
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
}
和上面删除基本上是一样的,调用这个System.arraycopy这个方法,这个方法是个本地方法。