ArrayList源码解析
先来一张UML类图
写几个常用的方法
- ArrayList的初始化构造方法
无参构造
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
*默认构造函数,构造一个空列表(无参数构造)
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
有参构造,传入一个初始化容量大小
transient Object[] elementData; // non-private to simplify nested class access
private static final Object[] EMPTY_ELEMENTDATA = {};
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {//初始化容量大于0
this.elementData = new Object[initialCapacity];//创建初始化容量大小的数组
} else if (initialCapacity == 0) {//初始化容量等于0
this.elementData = EMPTY_ELEMENTDATA;//创建一个空数组
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);//初始化容量小于0,抛出异常
}
}
构造一个包含指定集合中的元素,他们的顺序是由集合的迭代器返回一个列表。
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
ArrayList的常用方法
add方法
//默认容量
private static final int DEFAULT_CAPACITY = 10;
//要分配的最大数组大小
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
*将指定的元素追加到此列表的末尾
*/
public boolean add(E e) {
//添加元素之前先确保添加的元素有地方存储
ensureCapacityInternal(size + 1); // Increments modCount!!
//给数组赋值
elementData[size++] = e;
return true;
}
/**
*当要add进第1个元素时,minCapacity为1,在Math.max()方法比较后,minCapacity 为10。
*/
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
/**
*判断是否需要扩容
*/
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//grow就是ArrayList的扩容方法
grow(minCapacity);
}
//ArrayList扩容的核心机制
private void grow(int minCapacity) {
// overflow-conscious code
// oldCapacity为旧容量,newCapacity为新容量,>>1 为/2,新的容量为旧容量的1.5倍左右,因为旧容量可能为奇数
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果新容量小于最小需要容量,那么就把最小需要容量当作数组的新容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新容量大于MAX_ARRAY_SIZE则比较返回大的容量赋给新的容量
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
/**
*其实这里本质上还是调用了System.arraycopy()的方法
*/
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
/**
*其实这里本质上还是调用了System.arraycopy()的方法
*从index开始之后的所有成员后移一个位置;将element插入index位置;最后size加1。
*/
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;
}
//将元素添加到指定下标的位置
public void add(int index, E element) {
//首先对index进行边界检查
rangeCheckForAdd(index);
//调用 ensureCapacityInternal 方法保证capacity足够大
ensureCapacityInternal(size + 1); // Increments modCount!!
//从index开始之后的所有成员后移一个位置;将element插入index位置;最后size加1。
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
get方法
public E get(int index) {
//对index进行边界检查
rangeCheck(index);
//获取数组指定位置的元素
return elementData(index);
}
set方法
public E set(int index, E element) {
//边界检查
rangeCheck(index);
//获取指定位置(index)元素,放到oldValue存放
E oldValue = elementData(index);
//将需要设置的元素放到指定的位置(index)上
elementData[index] = element;
//将原来位置上的元素oldValue返回给用户
return oldValue;
}
remove方法
/**
*根据下标进行remove
*/
public E remove(int index) {
//边界检查
rangeCheck(index);
//自增修改次数
modCount++;
//获取指定位置(index)元素,放到oldValue存放
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
//将指定位置(index)上的元素都往前移动一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//将最后面的一个元素置空,但不会减少数组的长度
elementData[--size] = null; // clear to let GC do its work
//返回原来的值oldValue
return oldValue;
}
/**
*根据对象进行remove
*循环遍历所有对象,得到对象所在索引位置,然后调用fastRemove方法,执行remove操作
*/
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
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)
//将指定位置(index)上的元素都往前移动一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
clear方法
public void clear() {
//自增修改次数
modCount++;
// clear to let GC do its work
//循环遍历将数组中所有元素职位null,并将集合大小置为0
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
第一次写博客,ArrayList的源码是比较简单的,请大家多多指点!!!