类接口
直接上正菜,先看接口
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
}
接口的解释通常都会出现在接口源码的解释说明的第一行。
AbstractList抽象类: 抽象方法+已实现方法,看看就好
List: 方法接口
RandomAccess: List 实现该标记接口表示它们支持快速随机访问
Cloneable: 一个类实现了Cloneable 接口,表示 使用java.lang.Object#clone()方法进行按字段复制是合法的。
Serializable: 通过实现java.io.Serializable接口的类,可以启用类的可序列化性。
成员变量
再来看看成员变量
/**
* 序列化与反序列化时候用的
*/
private static final long serialVersionUID = 8683452581122892189L;
/**
* Default initial capacity. 默认初始化容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
* 当容量为0时,使用该实例
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances.
* 调用空参构造器时,使用该实例
* 我们将其与EMPTY_ELEMENTDATA区别开来,以了解添加第一个元素时需要充气多少。
* 看看ensureCapacityInternal(int minCapacity)方法
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* 存储数据的地方
*/
transient Object[] elementData;
/**
* The size of the ArrayList.
* 数组的大小
*/
private int size;
构造方法
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
*/
public ArrayList(int initialCapacity) {
//有容量,新建一个initialCapacity大小的数组
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//0容量,返回空数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* Constructs an empty list with an initial capacity of ten.
* 返回空数组
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
*/
public ArrayList(Collection<? extends E> c) {
//集合转数组
elementData = c.toArray();
//转过来的数组不为0时
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class)
//把不是Object[].class转成 Object[].class
elementData = Arrays.copyOf(elementData,size,Object[].class);
} else {
//为0,返回空数组
this.elementData = EMPTY_ELEMENTDATA;
}
}
扩容方法
/**
* Trims the capacity of this ArrayList instance to be the
* list's current size.
* 让数组压缩到合适大小
*/
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
/**
* Increases the capacity of this ArrayList instance
* @param minCapacity the desired minimum capacity
* 我怎么发现这个方法ArrayList类中都不用的?
*/
public void ensureCapacity(int minCapacity) {
//计算最小的扩展量
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// 如果为空参数构造方法构造的实例,那最小拓展数值为10
: DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
/**
* ArrayList中一般使用这个方法来进行扩容活动
*/
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);
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* 保留部分位置给虚拟机用
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* 扩容操作
*/
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
// newCapacity 为元素大小的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 复制数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
ArrayList在检验是否需要扩容的时候会调用ensureCapacityInternal(int minCapacity)
方法:
会存在几种扩容情况:
- elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
添加一个元素,扩容到DEFAULT_CAPACITY 大小
添加一个新集合:
新集合小于等于DEFAULT_CAPACITY ,扩容到DEFAULT_CAPACITY;
新集合大于DEFAULT_CAPACITY ,扩容到新集合; - elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA
添加一个新元素,如果size==elementData .length,容量扩大1.5倍;如果size<elementData .length,数组容量不变。
添加一个新集合,如果size+newArrr.length<=elementData .length,不扩容;反之,扩容1.5倍大小
以上没有考虑极端情况,设计到MAX_ARRAY_SIZE
的考虑
add方法
/**
* Appends the specified element to the end of this list.
*
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
/**
* Inserts the specified element at the specified position in this
* list.
* 在指定下标位置插入数据
*/
public void add(int index, E element) {
//边界检查
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1);
//数组挪位,从index开始的数据都往后走一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
/**
* Appends all of the elements in the specified collection to the end of
* this list, in the order that they are returned by the specified collection's Iterator.
* 在数组的结尾开始插入集合C中的数据
*/
public boolean addAll(Collection<? extends E> c) {
//转数组对象
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew);
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
//c为空数组,则返回false
return numNew != 0;
}
/**
* Inserts all of the elements in the specified collection into this
* list, starting at the specified position.
* 在数组指定下标的位置开始插入集合C中的数据
*/
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
//转数组
Object[] a = c.toArray();
//获取数组长度
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
//计算要挪位的位数
int numMoved = size - index;
if (numMoved > 0)
//挪位,空出numNew个位置
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
//入库
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
get方法
public E get(int index) {
//边界检查
rangeCheck(index);
return elementData(index);
}
//简单的检查
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
set方法
public E set(int index, E element) {
//边界检查
rangeCheck(index);
E oldValue = elementData(index);
//新值替换
elementData[index] = element;
//返回旧值
return oldValue;
}
E elementData(int index) {
return (E) elementData[index];
}
remove方法
//移除指定下标的数值
public E remove(int index) {
//边界检查
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
//计算需要位移的位数
int numMoved = size - index - 1;
if (numMoved > 0)
//数组从index+1开始左移一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
总结:
- ArrayList允许元素重复,元素可以为null
- 方法不同步,会出现线程安全问题
- 容器的初始容量为10,每次扩容后的容量为原始容量的1.5倍,添加集合情况另算。
- ArrayList的动态数组实现基于Arrays和System类的数组拷贝赋值方法