1、成员变量
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
/**
* 有初始化容量的构造参数
*/
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);
}
}
/**
* 构造一个空数组,使用默认容量10
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
2、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];
}
3、set()方法
public E set(int index, E element) {
rangeCheck(index); // 检查数组下标是否越界
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
4、add()方法
/**
* 在数组末尾插入元素
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
/**
* 在指定位置插入元素
*/
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
// 将数组中的元素从index开始,全部向后移动一个位置
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
/**
* 处理数组容量与扩容
*/
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);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length; // 老容量
int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量 = 老容量 + 老容量的一半
if (newCapacity - minCapacity < 0)
// 初始化时newCapacity=0
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) // 扩容后超过了最大数组容量
// 实际数组的长度+1 > MAX_ARRAY_SIZE 返回Integer.MAX_VALUE否则返回MAX_ARRAY_SIZE
newCapacity = hugeCapacity(minCapacity); // 最大是Integer.MAX_VALUE
// 复制数组,对多只能复制前Integer.MAX_VALUE个
elementData = Arrays.copyOf(elementData, newCapacity);
}
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; // 原数组中的元素被复制后左移,最后一个元素是重复的,要移除
return oldValue;
}
/**
* 移除list中第一个匹配的元素,将后续元素左移,如果没找到不做任何变动。
*/
public boolean remove(Object o) {
if (o == null) {
// 要删除的元素是null,遍历list,将遇到的第一个null元素删除
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
// 要删除的元素不是null,遍历list,将第一个相等的元素删除
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* 私有删除方法,没有索引范围检查,不反返回删除的元素
*/
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
}
6、clear()方法
/**
* 移除list里的所有元素
*/
public void clear() {
modCount++;
// 遍历数组,将每个元素设置成null
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
7、ArrayList和LinkedList比较
1、ArrayList底层数据结构是数组,LinkedList的是链表。
2、随机访问时,ArrayList直接通过索引访问元素;LinkedList只能遍历链表来查找。这种情况下ArrayList的效率比LinkedList效率高。
3、添加删除元素时,ArrayList需要将目标元素后面的所有元素向左或者向右移动1位;LinkedList只需要在两个节点之间插入即可,不需要移动其他元素的位置,这种情况下LinkedList的效率比ArrayList效率高。