ArrayList
ArrayList继承自AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable接口。ArrayList内部是一个动态数组,与Java中的数组相比,它的容量能动态增长。
ArrayList内部的属性
// 序列化id
private static final long serialVersionUID = 8683452581122892189L;
//ArrayList的初始容量大小
private static final int DEFAULT_CAPACITY = 10;
//空对象数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//空对象数组,如果使用默认构造函数创建,则默认对象内容默认是该值
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//存放当前数据,不参与序列化
transient Object[] elementData;
//list大小
private int size;
//list最大长度
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
ArrayList构造方法
//默认构造方法,默认容量是10,elementData初始化为DEFAULTCAPACITY_EMPTY_ELEMENTDATA
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//指定容量的构造方法,传入参数小于0抛出异常
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);
}
}
/**
*传入参数为Collection对象,先调用toArray()方法将Collection对象转换为Object[]
*更新size的值,同时判断size的大小,如果是size等于0,直接将空对象EMPTY_ELEMENTDATA的地址赋给elementData
*如果size的值大于0,则执行Arrays.copy方法,把collection对象的内容(可以理解为深拷贝)copy到elementData中,代码注释toArray可能不是返回Object[],所以进行深拷贝
**/
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主要方法
// 添加元素之前先检查容量,若容量不足则调用grow()方法,然后将元素添加到队尾,返回true
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
*首先检查index是否在size范围之内,确保数组已使用长度(size)加1之后足够存下一个数据
*然后将index之后的元素全部向后挪一位,再进行赋值
**/
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = element;
size++;
}
/**
*首先判断index是否超出范围,然后返回指定元素值
**/
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
/**
*首先判断index是否超出范围,然后将指定索引的数组元素赋值
**/
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
/**
*首先判断index是否超出范围,numMoved 计算移除元素后需要移动的元素个数
*通过System.arraycopy方法将后面的元素前移一位,并将最后一为赋值为null,最后返回移除元素的值
*/
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; // clear to let GC do its work
return oldValue;
}
/**
*需要遍历整个list去匹配移除元素的值
*/
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;
}
/**
*需要遍历整个list去匹配元素值,然后返回第一个匹配元素的索引值,否则返回-1
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
//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(minCapacity);
}
/**
*首先将oldCapacity 右移一位缩小1/2,newCapacity 扩大为oldCapacity 的1.5倍
*如果newCapacity不能满足需求,那就直接扩大为minCapacity大小
*如果newCapacity超过list最大容量,则返回Interger类型最大值
*最后更新elementData
**/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
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);
}