ArrayList is an array of variable length, is commonly used in the actual development, after analysis by parsing the source and record your own understanding.
ArrayList allowed into null;
ArrayList threads are not synchronized;
Inheritance (achieve) the relationship
extends
|---AbstractList<E>
implements
|---List<E>
|---RandomAccess
|---Cloneable
|---java.io.Serializable
Field
//序列化的版本号
private static final long serialVersionUID = 8683452581122892189L;
//默认的初始容量
private static final int DEFAULT_CAPACITY = 10;
//以含参构造函数创建且指定长度为0时使用的数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};
//以空参构造函数创建时使用的数组实例
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//存放元素的数组的引用
transient Object[] elementData;
//实际存放元素的个数
private int size;
Construction method
1. The no-argument constructor
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
Analysis: When creating ArrayList instance constructor with no arguments, the underlying array elementData reference point to a length of the array instance DEFAULTCAPACITY_EMPTY_ELEMENTDATA 0, the capacity is 0 at this time.
2. ① containing configuration parameters
public ArrayList(int initialCapacity) {
//如果指定的初始容量大于0,实例化一个长度为initialCapacity的数组,并赋值给elementData
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
/* 如果指定的初始化容量等于0,底层数组引用elementData会指向长度为0的数组实例
* EMPTY_ELEMENTDATA
*/
this.elementData = EMPTY_ELEMENTDATA;
} else {
//如果指定的初始化容量小于0,抛出异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
Analysis: The constructor can specify the initial capacity, the incoming parameters initialCapacity is the initial capacity.
3. ② containing configuration parameters
public ArrayList(Collection<? extends E> c) {
//将集合c转化为数组,赋值给elementData
elementData = c.toArray();
//如果数组长度不等于0
if ((size = elementData.length) != 0) {
//如果得到的数组不是一个Object[]类型的数组,将其转化为Object[]
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
else {
//如果数组长度为0,element指向EMPTY_ELEMENTDATA
this.elementData = EMPTY_ELEMENTDATA;
}
}
Analysis: The constructor can be configured to specify a set of elements comprises a set.
Dynamic growth mechanism :( expansion process)
A method to add elements add (E e) an example of the analysis of the dynamic growth mechanism ArrayList
1. Call add (E e) a method of increasing an element.
2. internally add (E e) method calls ensureCapacityInternal method. Determining whether a set of configuration parameters is instantiated empty, and if so, the default initial capacity (DEFAULT_CAPACITY = 10) as the minimum length required; if not, the minimum capacity size + 1 places as required.
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
3. Call ensureExplicitCapacity method within ensureCapacityInternal method. Determining a minimum required capacity exceeds the length of the current array.
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
4. If the minimum required length of the current exceeds the capacity of the array, the method calls for expansion grow. Try 1.5 times the original volume as a new volume newCapacity, if the new capacity is less than a minimum capacity minCapacity newCapacity required, then the required minimum length as the new minCapacity capacity. It is then determined whether the new capacity is larger than MAX_ARRAY_SIZE (Integer.MAX_VALUE-8), if exceeded, will Integer.MAX_VALUE as a new capacity, otherwise MAX_ARRAY_SIZE (Integer.MAX_VALUE-8) as a new capacity, assigned to the original length of the array newCapacity new array, the array length at this time really changed, the expansion is complete.
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
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)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
The main method
1.add (E e): add an element to the end of O (1)
public boolean add(E e) {
//判断是否扩容
ensureCapacityInternal(size + 1);
//将元素存放到末尾
elementData[size++] = e;
return true;
}
2.add (int index, E e): add an element to a specified position O (n)
public void add(int index, E element) {
//判断是否越界
rangeCheckForAdd(index);
//判断是否需要扩容
ensureCapacityInternal(size + 1);
//将将index位置之后的元素后移
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//将元素存放到index位置上
elementData[index] = element;
size++;
}
3.addAll (Collection <? Extends E> c): a collection of elements added in order to end the iteration
public boolean addAll(Collection<? extends E> c) {
//将集合c转为数组a
Object[] a = c.toArray();
//记录数组长度numNew
int numNew = a.length;
//判断是否需要扩容
ensureCapacityInternal(size + numNew);
//将数组a的复制到原数组或扩容后的数组中
System.arraycopy(a, 0, elementData, size, numNew);
//更新元素个数size
size += numNew;
return numNew != 0;
}
4.addAll (int index, Collection c <Extends E?>): A collection of elements added in order to specify the position of the iteration
public boolean addAll(int index, Collection<? extends E> c) {
//判断index是否越界
rangeCheckForAdd(index);
//将集合c转为数组a
Object[] a = c.toArray();
//记录数组长度numNew
int numNew = a.length;
//判断是否需要扩容
ensureCapacityInternal(size + numNew);
//计算需要移动的元素数量numMoved
int numMoved = size - index;
//如果numMoved>0,将index位置及其之后的元素后移numMoved个位置
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
//将a数组中的元素赋值到从index位置开始的numMoved个位置上
System.arraycopy(a, 0, elementData, index, numNew);
//更新元素个数size为size+numNew
size += numNew;
return numNew != 0;
}
5.remove (int index): Delete the specified position on the element O (n)
public E remove(int index) {
//判断index是否越界
rangeCheck(index);
modCount++;
//将index位置上的元素记录下来
E oldValue = elementData(index);
//将index位置之后的元素前移(覆盖index位置上元素)
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//将末尾元素置空(=null)
elementData[--size] = null;
//返回记录的index位置上的元素(oldValue)
return oldValue;
}
6.remove (Object o): Delete the first occurrence of a specified element
public boolean remove(Object o) {
//o如果为null,遍历数组并删除第一个为空的元素
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
//o如果不为null,遍历数组并删除第一个与o相同的元素
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
//如果没有找到该元素,返回false
return false;
}
7.removeAll (Collection c <?>): Delete all of the elements contained in the specified collection
public boolean removeAll(Collection<?> c) {
//判断集合c是否为null,如果为null,抛出NullPointerException
Objects.requireNonNull(c);
return batchRemove(c, false);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
//维护两个指针r,w,r用来遍历数组elementData,w用来记录不删除的元素存放位置
int r = 0, w = 0;
boolean modified = false;
try {
//遍历数组elementData中所有元素,依次判断是否存在于集合c中,如果没有,将其复制到w指针位置,w指针后移。
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
//判断r和w的位置,如果r没有移动到末尾(产生了异常中断了程序),将r指针及其之后的位置上的n元素向前移动到w指针位置,w指针后移n个位置。
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
//将w指针及其之后的元素置为null
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
8.set (int index, E e): the elements on the specified position specified element is replaced with O (1)
public E set(int index, E element) {
//判断index是否越界
rangeCheck(index);
//将index位置上的元素记录下来
E oldValue = elementData(index);
//将e覆盖到index位置
elementData[index] = element;
//返回记录的index位置上的元素
return oldValue;
}
9.get (int index): Gets the element at the specified location
public E get(int index) {
//判断index是否越界
rangeCheck(index);
return elementData(index);
}
@SuppressWarnings("unchecked")
E elementData(int index) {
//返回指定位置上的元素
return (E) elementData[index];
}
10.clear (): Delete all elements
public void clear() {
//修改计数+1
modCount++;
// 将所有元素置空
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
11.trimToSize (): set the capacity of the current element is the number of modified
public void trimToSize() {
//修改计数+1
modCount++;
//如果元素个数小于容量
if (size < elementData.length) {
//如果元素个数为0,将数组置为EMPTY_ELEMENTDATA,如果元素个数不为0,将数组长度调整为与元素个数相同
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
12.indexOf (Object o): Returns the index of the first occurrence in the collection of the specified element, if this list does not contain the element, or -1.
public int indexOf(Object o) {
//如果o为null,遍历数组并返回第一个为null的元素的位置
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
//如果o不为null,遍历数组并返回第一个与o相同的元素的下标
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
//如果没有找到,返回-1
return -1;
}
13.lastIndexOf (Object o): Returns the index of the last occurrence of the specified elements in this set, if the list does not contain the element, or -1.
public int lastIndexOf(Object o) {
//如果o为null,反序遍历数组并返回第一个为null的元素的位置
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
//如果o不为null,反序遍历数组并返回第一个与o相同的元素的下标
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
//如果没有找到,返回-1
return -1;
}
14.contains (Object o): if this list contains the specified element, it returns true.
public boolean contains(Object o) {
调用indexof(Object o),返回结果与0比较,返回比较结果。
return indexOf(o) >= 0;
}