ArrayList的实现原理
ArrayList底层是用一个数组实现的。
Object[] elementData;
当elementData装满元素时,会通过扩容的方式来增加elementData的容量
浅析ArrayList源码
添加元素
添加元素最常用的是boolean add(E e)方法,它实际上调用的是将元素插入的指定位置的方法void add(int index, E element)。
所以我们只需要搞懂void add(int index, E element)就可以了
public void add(int index, E element) {
rangeCheckForAdd(index); // 检查插入的位置是否超出数组范围
modCount++;
final int s;
Object[] elementData;
if ((s = size) == (elementData = this.elementData).length) // 判断是否需要扩容
elementData = grow(); // 扩容
System.arraycopy(elementData, index, // 将目标位置上及其后面的所有元素向后移动一位,如下图所示
elementData, index + 1,
s - index);
elementData[index] = element; // 把要插入的元素放到目标位置
size = s + 1;
}
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
例如add(2, 9)的执行流程如下
删除元素
public E remove(int index) // 删除指定位置上的元素
该方法的源码如下,可以看到是通过调用fastRemove(es, index)来删除元素的;
public E remove(int index) {
Objects.checkIndex(index, size);
final Object[] es = elementData;
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
fastRemove(es, index);
return oldValue;
}
fastRemove实现如下:
private void fastRemove(Object[] es, int i) {
modCount++;
final int newSize;
if ((newSize = size - 1) > i)
System.arraycopy(es, i + 1, es, i, newSize - i); // 将目标位置后面的所有元素前移一位
es[size = newSize] = null;
}
例如fastRemove(array, 2):
public boolean remove(Object o) // 删除元素o第一出现的位置
源码如下, 可以看到是先找到元素位置,再调用fastRemove删除
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
found: {
if (o == null) {
for (; i < size; i++)
if (es[i] == null)
break found;
} else {
for (; i < size; i++)
if (o.equals(es[i]))
break found;
}
return false;
}
fastRemove(es, i);
return true;
}
修改元素
修改元素的源码如下,比较简单
public E set(int index, E element) {
Objects.checkIndex(index, size);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
查找元素
public E get(int index) // 查找指定位置上的元素
源码如下,比较简单
public E get(int index) {
Objects.checkIndex(index, size);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
public int indexOf(Object o) // 查找元素第一次出现的位置
源码如下
public int indexOf(Object o) {
return indexOfRange(o, 0, size);
}
indexOfRange的源码如下, 也比较简单,就是通过for循环遍历素组,找到该元素后立即返回该元素的位置,如果遍历完还没找到则返回-1
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData;
if (o == null) {
for (int i = start; i < end; i++) {
if (es[i] == null) {
return i;
}
}
} else {
for (int i = start; i < end; i++) {
if (o.equals(es[i])) {
return i;
}
}
}
return -1;
}
public int lastIndexOf(Object o) // 查找元素最后一次出现的位置
源码如下
public int lastIndexOf(Object o) {
return lastIndexOfRange(o, 0, size);
}
lastIndexOfRange实现如下, 就是从数组的尾部向前遍历,找到该元素后立即返回该元素的位置,如果遍历完还没找到则返回-1
int lastIndexOfRange(Object o, int start, int end) {
Object[] es = elementData;
if (o == null) {
for (int i = end - 1; i >= start; i--) {
if (es[i] == null) {
return i;
}
}
} else {
for (int i = end - 1; i >= start; i--) {
if (o.equals(es[i])) {
return i;
}
}
}
return -1;
}