源码分析以JDK1.8为例.
ArrayList就是动态数组,就是Array的复杂版本.它提供了动态的增加和减少元素,实现了Collection和List接口,灵活的设置数组的大小等好处.UML图如下:
源码解读
公共属性
//默认容量
private static final int DEFAULT_CAPACITY = 10;
// 空数据
private static final Object[] EMPTY_ELEMENTDATA = {};
//默认容量空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//保存数据的数组
transient Object[] elementData;
//元素个数
private int size;
//最大数组长度
//一些虚拟机会在数组头部保存头信息,占用更多空间,导致OOM
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
无参构造器
//初始化一个空数组
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
int 构造器
指定初始容量,大于0直接初始化;等于0初始化一个空数组,小于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);
}
}
集合构造器
集合参数转化为对象数组赋值给元素集合,如果有元素判断集合类型,如果不是Object[] 执行集合复制转化为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 {
//初始化为空集合
this.elementData = EMPTY_ELEMENTDATA;
}
}
有一个注释,c.toArray 可能不会返回Object[].让参考bug编号6260652.到oracle 官网查看bug
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6260652
大意就是Arrays.asList 创建集合,再调用toArray返回的对象不是Object[]类型。测试一下看看:
public void test(){
List<Integer> obj = new ArrayList<>();
obj.add(32);
obj.add(344);
List<Integer> ls = new ArrayList<>(obj);
System.out.println(ls.size());
Object[] c = obj.toArray();
System.out.println(c.getClass());
System.out.println(Object[].class);
//Arrays.asList创建
List<Integer> d = Arrays.asList(3,2,3);
System.out.println(d.toArray().getClass());
}
2
class [Ljava.lang.Object;
class [Ljava.lang.Object;
class [Ljava.lang.Integer;
可见Arrays.asList 返回的是Integer[],并非Object[].
查看Arrays相关源码
//初始化ArrayList
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
此处的ArrayList为Arrays的内部类.
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
//泛型数组
private final E[] a;
//初始化
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
@Override
public int size() {
return a.length;
}
//调用a的clone方法
@Override
public Object[] toArray() {
return a.clone();
}
@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class<? extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
}
官方显示,JDK9已经解决。
扩展一下,查看数组的clone方法,length属性的实现.
public void test(){
int [] a = {1,2,3};
System.out.println(a.length);
}
public static void test2(){
Integer[] f = {3,4};
f.clone();
}
查看byte code
public class com.xwolf.ArrayListTest {
public com.xwolf.ArrayListTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public void test();
Code:
0: iconst_3
1: newarray int
3: dup
4: iconst_0
5: iconst_1
6: iastore
7: dup
8: iconst_1
9: iconst_2
10: iastore
11: dup
12: iconst_2
13: iconst_3
14: iastore
15: astore_1
16: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: arraylength
21: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
24: return
public static void test2();
Code:
0: iconst_2
1: anewarray #4 // class java/lang/Integer
4: dup
5: iconst_0
6: iconst_3
7: invokestatic #5 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
10: aastore
11: dup
12: iconst_1
13: iconst_4
14: invokestatic #5 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
17: aastore
18: astore_0
19: aload_0
20: invokevirtual #6 // Method "[Ljava/lang/Integer;".clone:()Ljava/lang/Object;
23: pop
24: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #7 // Method test2:()V
3: return
}
此处不展开,arraylength、invokevirtual参考官网java虚拟机规范https://docs.oracle.com/javase/specs/jvms/se8/html/index.html.
add方法
//List后追加元素
public boolean add(E e) {
//扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(ca lculateCapacity(elementData, minCapacity));
}
//计算容量,元素为空返回默认容量和容量的最大值
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//扩容到指定容量,修改次数modCount加1
private void ensureExplicitCapacity(int minCapacity) {
//增加修改次数
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
//old容量为元素数组的元素个数
int oldCapacity = elementData.length;
// 扩容至 old + (old/2)
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//超过最大容量值,扩容至Integer的最大值
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);
}
//大容量,容量值小于0抛出异常,容量值大于最大数组长度返回Integer的最大值2^31-1
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
add(int index, E element)
//指定位置添加元素
public void add(int index, E element) {
//边界检查
rangeCheckForAdd(index);
//扩容
ensureCapacityInternal(size + 1);
//将指定位置后的元素复制到扩容后的元素集合中
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//指定位置赋值
elementData[index] = element;
size++;
}
//边界检查
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/* @param src the source array.
* @param srcPos starting position in the source array.
* @param dest the destination array.
* @param destPos starting position in the destination data.
* @param length the number of array elements to be copied.
*/
//将src的srcPos的连续length个元素复制到dest的destPos的连续位置(替换)
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
add 集合
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
//将集合元素追加到elementData后
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
指定位置添加集合
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)
//先将指定位置后的元素copy移动后指定位置的元素
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
//将空出来的元素用添加的集合参数赋值
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
上图,更直观一点:
remove 指定索引位置的元素
public E remove(int index) {
//边界检查
rangeCheck(index);
//增加修改次数
modCount++;
//获取指定索引位置的元素
E oldValue = elementData(index);
//需要移动的元素的数量
int numMoved = size - index - 1;
if (numMoved > 0)
//将index后的元素向前移动一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//size减1,最后一个元素赋值null,等待GC处理
elementData[--size] = null; // clear to let GC do its work
//返回删除的元素
return oldValue;
}
remove指定的元素
//遍历删除指定的元素
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;
}
//快速移除
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
}
set
public E set(int index, E element) {
//边界检查
rangeCheck(index);
E oldValue = elementData(index);
//赋新值
elementData[index] = element;
return oldValue;
}
get
public E get(int index) {
//边界检查
rangeCheck(index);
//返回指定索引元素
return elementData(index);
}
indexOf
//遍历获取第一个元素的索引,找不到返回-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;
}
contains
//索引大于0即为包含指定元素
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
trimToSize
将容量和实际数组元素个数保持一致,删除扩容的null元素.
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
retainAll
获取两个集合的交集
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
//如果包含元素直接赋值
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
//如果循环异常中断,正常情况下r==size
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
//如果w!=size ,将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;
}
iterator
迭代
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
//是否还有下一个元素
public boolean hasNext() {
return cursor != size;
}
//获取下一个元素
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
//删除元素
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
//检查修改
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
subList
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
//边界检查
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
}
//内部类
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
sort
只需要知道sort内部是归并排序和Tim Sort即可.此处不展开详细的排序算法.
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
public static <T> void sort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
if (c == null) {
sort(a, fromIndex, toIndex);
} else {
rangeCheck(a.length, fromIndex, toIndex);
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, fromIndex, toIndex, c);
else
TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
}
}
// legacyMergeSort
private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
T[] aux = copyOfRange(a, fromIndex, toIndex);
if (c==null)
mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
else
mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
}
//mergeSort 归并排序
private static void mergeSort(Object[] src,
Object[] dest,
int low,
int high,
int off) {
int length = high - low;
// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
// Recursively sort halves of dest into src
int destLow = low;
int destHigh = high;
low += off;
high += off;
int mid = (low + high) >>> 1;
mergeSort(dest, src, low, mid, -off);
mergeSort(dest, src, mid, high, -off);
// If list is already sorted, just copy from src to dest. This is an
// optimization that results in faster sorts for nearly ordered lists.
if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}
// Merge sorted halves (now in src) into dest
for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
dest[i] = src[p++];
else
dest[i] = src[q++];
}
}
///TimSort.sort
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
T[] work, int workBase, int workLen) {
assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
int nRemaining = hi - lo;
if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted
// If array is small, do a "mini-TimSort" with no merges
if (nRemaining < MIN_MERGE) {
int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
binarySort(a, lo, hi, lo + initRunLen, c);
return;
}
/**
* March over the array once, left to right, finding natural runs,
* extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant.
*/
TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// Identify next run
int runLen = countRunAndMakeAscending(a, lo, hi, c);
// If run is short, extend to min(minRun, nRemaining)
if (runLen < minRun) {
int force = nRemaining <= minRun ? nRemaining : minRun;
binarySort(a, lo, lo + force, lo + runLen, c);
runLen = force;
}
// Push run onto pending-run stack, and maybe merge
ts.pushRun(lo, runLen);
ts.mergeCollapse();
// Advance to find next run
lo += runLen;
nRemaining -= runLen;
} while (nRemaining != 0);
// Merge all remaining runs to complete sort
assert lo == hi;
ts.mergeForceCollapse();
assert ts.stackSize == 1;
}
总结
- 初始容量为10
- 动态扩容容量为 old + old/2
- 随机查找效率较高
- 插入和删除慢,需要移动元素
- 排序用归并排序和TimSort
- 动态删除元素会抛出异常,可用迭代器实现
- 线程不安全
参考
如有错误,欢迎批评指正,望不吝赐教!!!