源码分析以JDK1.8为例.html
ArrayList就是动态数组,就是Array的复杂版本.它提供了动态的增长和减小元素,实现了Collection和List接口,灵活的设置数组的大小等好处.UML图以下:java
源码解读
公共属性
//默认容量 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[]类型。测试一下看看:oracle
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相关源码dom
//初始化ArrayList @SafeVarargs @SuppressWarnings("varargs") public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
此处的ArrayList为Arrays的内部类.jvm
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属性的实现.ide
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
- 动态删除元素会抛出异常,可用迭代器实现
- 线程不安全
参考
若有错误,欢迎批评指正,望不吝赐教!!!