ArrayList继承关系
public class ExtArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
它继承于 AbstractList
,实现了 List, RandomAccess, Cloneable, java.io.Serializable
这些接口。
ArrayList
继承了AbstractList
,实现了List
。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
ArrayList
实现了RandomAccess
接口, RandomAccess
是一个标志接口,表明实现这个这个接口的 List 集合是支持快速随机访问的。在 ArrayList
中,我们即可以通过元素的序号快速获取元素对象,这就是快速随机访问。
ArrayList
实现了Cloneable
接口,即覆盖了函数 clone()
,能被克隆。
ArrayList
实现java.io.Serializable
接口,这意味着ArrayList
支持序列化,能通过序列化去传输。
ArrayList实现原理
内部是使用数组,进行存储数据
默认初始容量为10,以10 + 10>>1的大小扩容
使用System.arraycopy()方法进行扩容
ArrayList remove方法也是通过System.arraycopy()方法实现,移动元素之后,将最后一个元素置为null
remove删除对象,通过for循环,将全部数组元素遍历,使用equals判断对象是否相等,然后调用remove(int index)方法将对象删除
/**
* 添加元素方法
*/
public boolean add(E e) {
//判断是否需要进行扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
* 判断是否需要进行扩容
* @param minCapacity
*/
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/**
* 判断是否可以进行扩容
* @param minCapacity
*/
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
//如果最小容量比原数组容量大,进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 扩容数组方法
*
* @param minCapacity 自定义最小容量大小
*/
private void grow(int minCapacity) {
// 原数组大小
int oldCapacity = elementData.length;
//获取新的容量大小,使用位移算法 >>
int newCapacity = oldCapacity + (oldCapacity >> 1);
//这一步是防止原数组容量为空或者为1,然后新的容量大小计算出错
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新的容量大小超过了数组的最大容量大小,则使用数组的最大容量大小
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 调用扩容方法
elementData = Arrays.copyOf(elementData, newCapacity);
}
/**
* 删除数组元素方法
* @param index 数组元素下标
*/
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);
//将最后一个元素赋值为null,为了让GC回收
elementData[--size] = null;
return oldValue;
}
/**
* 检查下标是否超过数组元素大小
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 获取指定下标元素
* @param index 下标
*/
public E get(int index) {
//判断下标是否越界
rangeCheck(index);
return elementData(index);
}
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
Arraylist扩容机制
System.arraycopy()
与Arrays.copyOf()
的区别ArrayList
底层是使用Arrays.copyOf()
方法实现扩容
/**
* @param src 源数组
* @param srcPos 源数组的拷贝起点位置
* @param dest 目标数组
* @param destPos 放入没有标数组的起点位置
* @param length 需要拷贝源数组长度
* /
System.arraycopy(Object src, int srcPos,Object dest, int destPos,int length);
Arrays.copyOf()
底层是使用System.arraycopy()
方法实现copyOf
方法在内部新建一个Object[]
数组,将数组扩容后的值赋值给新数组
/**
* @param original 需要被拷贝的数组
* @param newLength 新数组的长度
* @param newType 拷贝的数组的返回值类型
*/
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@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;
}
ArrayList和Vector区别
扩容容量的大小不同
//Vector
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?capacityIncrement : oldCapacity);
//ArrayList
int newCapacity = oldCapacity + (oldCapacity >> 1);
ArrayList线程不安全
Vector给需要修改值的方法加上了synchronized关键字。