ArrayList的源码实现
1. Arraylist 的相关属性
/**
* 默认设置数组长度: 10
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 一个空的数组
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 一个默认为空容量的数组(obj)
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 集合中存储数据的数组对象,transient表示不可以序列化
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* 用来表示list的长度(list中元素的数量)
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
2. 构造方法
a.无参的构造方法
public ArrayList() {
//直接将空数组赋值给用来存储元素的elementData数组(默认数组为{})
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
b.有参的构造方法
public ArrayList(int initialCapacity) {
//如果传入的参数大于0,将传入的initialCapacity长度的数组赋值给 //elementData;传入参数为0数组赋值为空数组;否则抛出异常
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
c. 构造一个包含指定集合的元素列表
/**
* Collection<? extends E> c 的意思是
* Collection<? extends E>解释:
* 1.实现了Collection接口
* 2.类型一定是E的子类
* 符号解释: ?:通配符
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray 有可能不返回一个 Object 数组
if (elementData.getClass() != Object[].class)
//使用 Arrays.copy 方法拷创建一个 Object 数组
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
小结构造方法
调用有参构造方法时,如果给定初始容量为0,或者传入集合为空集合(不是null),那么,将空数组EMPTY_ELEMENTDATA赋给elementData,此时在添加第一位元素时,不会扩容为10。(具体add方法分析)
3.add()方法
1.模拟无参构造方法第一次add的情况
public boolean add(E e) {
// 确定容量,动态扩容 无参构造size为0
ensureCapacityInternal(size + 1);
// 将元素放入对应位置
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) { //minCapacity为size + 1=1
//先分析calculateCapacity
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//初始化数组容器为默认,第一次添加没有动态扩容为==
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//所以第一次返回是10(取两者大值,DEFAULT_CAPACITY默认数组长度是10)
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//如果不是第一次或者无参构造的话那么在这里直接返回 数组长度+1(if不成立的话就是返回传入参数:minCapacity)
return minCapacity;
}
回到上一个方法: ensureExplicitCapacity
//动态扩容方法
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //这个最后单独说 是一种快速失败抛出并发异常的机制
// overflow-conscious code
// 如果传入的minCapacity大于原来数组的长度,执行grow方法进行扩容
// 第一次 10 > 0
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //原来数组的长度 0
/**
* 位运算:下面的意思是新数组长度为 10 + 10的2进制右移位运算 10 的二进制为1010 --> 0101 *(4+1=5)newCapacity=15
*/
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果newCapacity - minCapacity < 0 将newCapacity赋值为传入的minCapacity
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)//如果长度超过int的最大长度 2的32次方-1
//newCapacity小于0抛出异常,如果大于MAX_ARRAY_SIZE属性的话(Integer.MAX_VALUE - 8),赋值为int类型的最大值(2的32次方),否则为MAX_ARRAY_SIZE
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 第一次就是走这里将原本为空的数组赋值为长度为10的数组,完成动态扩容
elementData = Arrays.copyOf(elementData, newCapacity);
}
最后回到add方法
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
//最后将元素放入指定位置
elementData[size++] = e;
return true;
}
2. 模拟第2次添加
public boolean add(E e) {
// size + 1 = 2
ensureCapacityInternal(size + 1);
// 将元素放入对应位置 size++使用后自增
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) { // 2
//先分析calculateCapacity
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//直接返回2
return minCapacity;
}
//动态扩容方法
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
//2<10,不执行grow扩容方法直接回到add方法开始添加元素到data[1]位置
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
3. 模拟第11次添加
public boolean add(E e) { //{1,2,3,4,5,6,7,8,9,10} 11
//11
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) { //minCapacity为size + 1=1
//先分析calculateCapacity
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) { // 11
//初始化数组容器为默认,第一次添加没有动态扩容为==
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//所以第一次返回是10(取两者大值,DEFAULT_CAPACITY默认数组长度是10)
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//如果不是第一次或者无参构造的话那么在这里直接返回 数组长度+1(if不成立的话就是返回传入参数:minCapacity)
return minCapacity;
}
//动态扩容方法
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
//11-10>0
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length; //10
int newCapacity = oldCapacity + (oldCapacity >> 1); //15
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 给一个15的数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
//回到add方法给新数组赋值
4.get()方法
public E get(int index) {
//校验长度是否索引越界判断
rangeCheck(index);
//直接返回对应数组位置的值
return elementData(index);
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
5.set()方法
//校验,替换,返回旧值
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
6.remove方法
//根据位置删除
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
//numMoved等于数组元素-索引位置-1.如果numMoved等于0。说明删除的元素是最后一位,
//然后跳过if语句。
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;
}
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:源数组;
srcPos:源数组要复制的起始位置;
dest:目的数组;
destPos:目的数组放置的起始位置;
length:复制的长度.