1,ArrayList简介
ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访 问。稍后,我们会比较List的“快速随机访问”和“通过Iterator迭代器访问”的效率。ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输,和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。2,设计原理
(01) ArrayList 实际上是通过一个数组去保存数据的。当我们构造ArrayList时;若使用默认构造函数,则ArrayList的默认容量大小是10。(02) 当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 + 1”。
(03) ArrayList的克隆函数,即是将全部元素克隆到一个数组中。
(04) ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。
3,源码分析
1,构造方法// 默认构造函数 ArrayList()
// capacity是ArrayList的默认容量大小。当由于增加数据导致容量不足时,容量会添加上一次容量大小的一半。
ArrayList(int capacity)
// 创建一个包含collection的ArrayList
ArrayList(Collection<? extends E> collection)
2,成员变量
ArrayList包含了两个重要的对象:elementData 和 size。
(01) elementData 是"Object[]类型的数组",它保存了添加到ArrayList中的元素。实际上,elementData是个动态数组,我们能通过构造函数 ArrayList(int initialCapacity)来执行它的初始容量为initialCapacity;如果通过不含参数的构造函数ArrayList()来创建ArrayList,则elementData的容量默认是10。elementData数组的大小会根据ArrayList容量的增长而动态的增长,具体的增长方式,请参考源码分析中的ensureCapacity()函数。
(02) size 则是动态数组的实际大小。
3, 方法
这里只介绍一个常用的方法:
3.1 add方法
public boolean add(E e) {
//往数组添加元素前,先检查数组容量够不够
ensureCapacityInternal(size + 1);
//将元素添加到数组对应的位置上去
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
//如果为空数组,则minCapacity取minCapacity和10的最大值,默认数组中存放10个元素
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);
}
private void grow(int minCapacity) {
// 原数组长度
int oldCapacity = elementData.length;
//新数组长度 = 原数组长度 + 原数组长度的一半 也就是原数组长度的1.5倍
// 运算符 >> 是带符号右移. 如 oldCapacity = 10,则 newCapacity = 10 + (10 >> 1) = 10 + 5 = 15
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果扩容1.5倍后还不够,则新数组长度等于当前元素的个数
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 若 newCapacity 大于最大存储容量,则进行大容量分配,数组容量分配了Integer的最大值
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//最后调用Arrays.copyOf将数组进行克隆,得到一个新的容量的数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
//Arrays数组工具类的copyOf方法:original参数为元素组,newLength参数为新数组大小
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
public static byte[] copyOf(byte[] original, int newLength) {
byte[] copy = new byte[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
//jdk1.0 System的arraycopy方法是一个本地方法,底层是用C或C++语言实现,这里就不说了
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,int length);
3.2 remove方法
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
}
5.3 sort方法
//ArrayList中也有排序的方法,给sort方法传一个自定义的比较器(实现comparator接口)或者元素自身是一个比较器(实现comparable接口)
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
3.4 subList方法
public List<E> subList(int fromIndex, int toIndex) {
//参数检查
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0) //起始下标不能为空
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size) //末尾下标不能大于数组长度
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)//起始下标不能大于末尾下标
throw new IllegalArgumentException("fromIndex(" + fromIndex +") > toIndex(" + toIndex +")");
}
private class SubList extends AbstractList<E> implements RandomAccess {
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
//parent为new SubList(this, 0, fromIndex, toIndex)中的this对象
//parent也就是到截取的数组对象
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
这个子类中也定义了自己的一些方法,这里没有列举出
}