一、ArrayList简介
ArrayList的底层是一个数组,刚开始有一定的大小,随着加入的元素增多后,底层数组会扩容。
二、ArrayList构造方法
1、ArrayList()
底层初始化一个空的对象数组。
2、ArrayList(int initialCapacity)
底层初始化一个对象数组,数组的长度为initialCapacity,数组最后一项为elementData[initialCapacity-1]。
3、ArrayList(Collection<? extends E> c)
将实现Collection接口的集合转换为对象数组,赋值给ArrayList的底层数组。
三、ArrayList.add(E)插入元素
第一步:判断对象数组空间是否已满,如果已满或数组长度为0,则进行扩容;如果空间未满,则直接跳到第二步;
扩容:当数组长度为0时,数组长度初始化为DEFAULT_CAPACITY=10(在Java8中,DEFAULT_CAPACITY变量只用到了这一次);接下来的扩容,数组长度增加原大小右移1位(oldCapacity >> 1),即扩容后数组长度=扩容前数组长度+扩容前数组长度二进制右移一位。最终通过Arrays.copyOf()进行扩容。
第二步:将加入的对象放入数组第一个非空位置。
四、ArrayList.get(int)查找元素
第一步:检查入参数值是否小于集合中元素的个数,如果不是,则报出IndexOutOfBoundsException;
private void rangeCheck(int index) {
if (index >= size)//这个size是集合中元素的个数
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
第二步:返回对象数组中,如参数值对应位置的对象
E elementData(int index) {
return (E) elementData[index];
}
五、ArrayList.remove()移除元素
1、通过下标移除元素:ArrayList.remove(int)
public E remove(int index) {
rangeCheck(index);//第一步:检查入参数值是否小于集合中元素的个数,如果不是,则报出IndexOutOfBoundsException
modCount++;
E oldValue = elementData(index);//第二步:找出入参下标对应的对象
//第三步:将入参下标后面的元素全部向前移动一位(通过System.arraycopy()实现)
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--size] = null;//第四步:记录集合元素个数的变量减一,原数组中最后一个非空位置置为空
return oldValue;
}
2、通过对象移除元素:ArrayList.remove(java.lang.Object)
第一步:通过入参对象找到元素所在位置的下标(用for循环查找);
第二步:通过下标将元素移除,与ArrayList.remove(int)不同的是,这里没有检查下标是否越界(因为没有必要)。
六、ArrayList总结
- ArrayList的底层是一个数组,这个数组可以扩容;
- ArrayList的所有方法都是线程不安全的,使用需要考虑是否合适。