ArrayList源码解析
-
简介
ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。
ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。
ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了Cloneable接口,能被克隆。
*由add()方法中检查扩容操作可以看出:ArrayList初始化时最好指定可预测的数组长度,避免扩容导致系统消耗
-
构造函数
/**
Constructs an empty list with an initial capacity of ten.
构造初始容量为10的空列表。
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Constructs an empty list with the specified initial capacity.
*用指定的初始容量构造空列表。
* @param initialCapacity the initial capacity of the list
初始容量列表的初始容量
* @throws IllegalArgumentException if the specified initial capacity is negative
指定的初始容量为负
*/
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);
}
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*构造包含指定集合的元素的列表,按集合的迭代器返回这些元素的顺序
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
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;
}
}
- 插入数据
/**
* Appends the specified element to the end of this list.
*将指定的元素追加到此列表的末尾。
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
//检测是否扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*在此列表中的指定位置插入指定元素。将当前位于该位置的元素(如果有)和任何后续元素向右移动(将一 个元素添加到其索引中)。
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
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++;
}
- 扩容检查
/**
检查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++;
// overflow-conscious code
//如果长度-数组长度>0,进行扩容处理
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//新的数组长度 = 旧长度+旧长度*0.5(即:arrayList默认扩容1.5倍)
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);
}
-
删除方法
-
//根据下标删除 public E remove(int index) { //检查下标是否越界 rangeCheck(index); //增加操作次数 modCount++; //获取下标对应的元素 E oldValue = elementData(index); //数据移动量 //将index+1及之后的元素向前移动一位 //例: size =10 当前数组最大index =9 //对应index为0,1,2,3,4,5,6,7,8,9 //index =2 则需要将index为3,4,5,6,7,8,9的数据向前移动一位 //即:对应的移动量为 size-index-1 =7 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 boolean remove(Object o) { //判断元素是否为null 如果为null 则删除第一个为null的元素下标 if (o == null) { for (int index = 0; index < size; index++) //找出第一个为null的下标,根据下标进行删除 if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) //找出第一个元素为o的下标,根据下标进行删除 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) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }