(一)List子父层级
List接口继承于Collection,Collection继承Iterable;
LIst接口实现类分为:Vector、ArrayList、LinkedLIst;
(二)List实现类
1、ArrayList实现类
(1)ArrayList底层是Object数组,transient Object[] elementData;
(2)ArrayList默认容量为10或者构造方法指定初始容量,private static final int DEFAULT_CAPACITY = 10;
(3)ArrayList扩容是基于当前容量的1.5倍,int newCapacity = oldCapacity + (oldCapacity >> 1);
(4)ArrayList是线程不安全的,在多线程环境下,会报并发修改异常java.util.ConcurrentModificationException。
2、常见源码
(1)构造方法:
//无参构造方法,未指定初始容量
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//将空数组对象赋值给存储数组
}
//有参构造方法,指定初始容量进行初始化
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];//以传入值对存储数组进行初始化
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;//赋值空数组初始化存储数组
} else {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
(2)add方法:
//此处列举常用add(返回值为boolean),其它指定位置插入add(返回空)方法暂不列举,逻辑基本类似
public boolean add(E e) {
ensureCapacityInternal(size + 1);//判断是否需要扩容
elementData[size++] = e;//将值存储在数组上
return true;
}
//判断是否需要扩容,如需要则进行1.5倍扩容
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//判定并计算容量大小值(旧的size+新的1)
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//判断是否已被初始化
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;//返回实际已存值大小(size)+将要存储值大小(1)
}
//扩容判定
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//操作次数
if (minCapacity - elementData.length > 0)//判定当前数组是否还能存入值
grow(minCapacity);//扩容
}
//数组最大值
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
int oldCapacity = elementData.length;//当前数组长度
int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容新数组大小(利用位运算进行1.5倍扩大)
if (newCapacity - minCapacity < 0)//判定扩容后大小是否仍然不满足存储要求
newCapacity = minCapacity;//不满足要求的前提下,直接将满足值设置为扩容后的数值
if (newCapacity - MAX_ARRAY_SIZE > 0)//判定是否超过数组最大值
newCapacity = hugeCapacity(minCapacity);//扩容值超大设置
elementData = Arrays.copyOf(elementData, newCapacity);//数组数据迁移复制
}
//判定扩容后的容量是否是超大值
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) //越界值判定
throw new OutOfMemoryError();
//返回扩大值,既可能是Integer最大值也可能是数组最大值
return (minCapacity > MAX_ARRAY_SIZE)?Integer.MAX_VALUE:MAX_ARRAY_SIZE;
}
(3)get方法:
public E get(int index) {
rangeCheck(index);//越界检查
return elementData(index);
}
//越界检查方法
private void rangeCheck(int index) {
if (index >= size)//越界检查
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//获取索引数据
E elementData(int index) {
return (E) elementData[index];//直接将对应索引数据返回
}
(4)set方法:
public E set(int index, E element) {
rangeCheck(index);//检查是否越界,不列举,上述(3)中已列举
E oldValue = elementData(index);//获取指定索引已存在的值
elementData[index] = element;//将新值设置到指定索引位置
return oldValue;//返回旧值
}
(5)remove方法:
//暂只列举根据索引删除数组值,不列举其他参数删除(原理大体相同)
public E remove(int index) {
rangeCheck(index);//数组越界检查
modCount++;//操作次数
E oldValue = elementData(index);//获取指定索引数组值
int numMoved = size - index - 1;//需要移动的数组长度
if (numMoved > 0)//判定因为删除指定索引值后是否需要移动后面的数组值
System.arraycopy(elementData, index+1, elementData, index, numMoved);//系统复制数组
elementData[--size] = null; //将因删除而导致的空位置空,便于GC
return oldValue;//将删除的值返回
}
3、总结
(1)ArrayList线程不安全,并发操作ArraylList会报并发修改异常java.util.ConcurrentModificationException。
(2)ArrayList默认容量为10(构造方法未指定初始容量为0),扩容是利用位运算(右移一位)和直接相加进行1.5倍扩容。