目錄java
java.util.ArrayList 是咱們最經常使用的一個類,ArrayList 底層是動態數組,讀者能夠把它理解爲數組的實現數組
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ }
如上代碼咱們能夠看到 ArrayList 繼承了 AbstractList() 抽象類,並實現了 List, RandomAccess, Cloneable, Serializable 接口安全
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {}
能夠看到AbstractList 繼承了 AbstractCollection 接口, 並實現了List 接口dom
public abstract class AbstractCollection<E> implements Collection<E> {}
AbstractCollection 是一個抽象類,實現了Collection 接口,並提供了某些方法的具體實現。ide
Collection 是一個頂級接口,是不少集合類的頂級接口,繼承了Iterable ,支持輕量級遍歷其中元素源碼分析
public interface Collection<E> extends Iterable<E> {}
ArrayList 實現了List接口,List 也是一個和Collection 媲美的頂級接口,繼承了Collection 接口ui
public interface List<E> extends Collection<E> {}
它是許多集合類的父類,this
eg:debug
List list = new ArrayList(); List list2 = new LinkedList();
RandomAccess 也是一個頂級接口,實現了此接口的類支持隨機訪問3d
Cloneable 接口是一個頂級接口,實現了此接口的類支持淺拷貝
實現此接口的類支持序列化的功能
類之間的繼承關係如圖
trimToSize()
實踐纔是檢驗真理最好的方式:
import java.util.*; /** * 詳述ArrayList 基本用法 */ public class ArrayListTest { private static class SortList implements Comparator<String> { @Override public int compare(String o1, String o2) { Integer i1 = Integer.valueOf(o1); Integer i2 = Integer.valueOf(o2); if(i1 < i2){ return -1; }else if(i1 == i2){ return 0; } return 1; } } // 使用可變參數,可以接受任意個參數 public Set<String> putSet(String...args){ Set<String> sets = new HashSet<>(); for(String str : args){ sets.add(str); } return sets; } public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("111"); list.add("222"); // 在指定位置添加元素 list.add(0,"333"); System.out.println(list); // 進行外部排序 list.sort(new SortList()); System.out.println(list); list.clear(); System.out.println(list.size()); // 使用addAll添加元素 ArrayListTest at = new ArrayListTest(); list.addAll(at.putSet("1","2","3")); Iterator<String> it = list.iterator(); while(it.hasNext()){ System.out.println(it.next()); // 移除全部元素 it.remove(); } System.out.println("list是否爲空 ? " + list.isEmpty()); list.add("111"); // 在指定位置添加一個set集合 list.addAll(0,at.putSet("1","2","3")); System.out.println(list); // 是否包含指定元素 if(list.contains("111")) { list.remove("111"); } System.out.println(list); System.out.println(list.indexOf("1")); // 注意subList()這個方法是左開右閉區間,Java 中不少都是相似的 System.out.println(list.subList(0,3)); // 擴大list的容量 list.ensureCapacity(10); // 去掉list空閒的容量 list.trimToSize(); // 獲取某個特定的元素 System.out.println(list.get(1)); // 建立一個list的雙向鏈表 ListIterator<String> listIterator = list.listIterator(); while(listIterator.hasNext()){ // 移到list的末端 System.out.println(listIterator.next()); } System.out.println("--------------------------"); while (listIterator.hasPrevious()){ // 移到list的首端 System.out.println(listIterator.previous()); } // 把list轉換爲數組 Object[] objects = list.toArray(); System.out.println("objects = " + objects); } }
源碼的具體分析是根據上面的代碼示例得出,由於只看源碼好像並不能看懂什麼,須要根據具體的代碼一步一步debug 進行跟蹤
add()方法
解釋:添加指定的元素在list的末尾
/** * 添加指定的元素在list的末尾 */ // 假設第一次添加的是 "111" public boolean add(E e) { // size是0,因此size + 1 傳的是1 ensureCapacityInternal(size + 1); // elementData[0] = 111 , size++ = 1 elementData[size++] = e; return true; } // 此方法用來進行list 擴容 private void ensureCapacityInternal(int minCapacity) { // 此時elementData 並無存儲元素,爲0 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 則minCapacity 取默認初始容量和minCapacity 的最大值 (取1 和 10的最大值) minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } // 確保清晰的容量(最小容量與List元素的比較) ensureExplicitCapacity(minCapacity); } // 在list中添加了一個元素,因此會致使結構化的修改,"結構化的修改"見下面解釋 // 此時minCapacity 爲 10 private void ensureExplicitCapacity(int minCapacity) { // 次數 + 1 // 這個列表被修改結構的次數(好比添加和刪除元素)會用modCount表示. 結構化修改是指的是可以 // 改變列表容量的操做,或者其餘方式改變它,致使遍歷的過程會產生錯誤的結果。 modCount++; // overflow-conscious code // 10 - 0 > 0 走grow 方法 if (minCapacity - elementData.length > 0) grow(minCapacity); } /** * 增長容量確保容納足夠的元素 * * 參數傳過來的是10 */ private void grow(int minCapacity) { // overflow-conscious code // oldCapacity = 0 int oldCapacity = elementData.length; // newCapacity = 0 int newCapacity = oldCapacity + (oldCapacity >> 1); // newCapacity - minCapacity = -10 if (newCapacity - minCapacity < 0) // newCapacity = 10 newCapacity = minCapacity; // MAX_ARRAY_SIZE = 數組分配的最大空間 = 2147483639 // 通常狀況下不會比 MAX_ARRAY_SIZE 還要大 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: // 底層仍是用的System.arraycopy(), 關於System.arrayCopy() 讀者能夠參考個人另外一篇博客 elementData = Arrays.copyOf(elementData, newCapacity); }
相關經常使用的基本數據類型包裝類的值: Java基本數據類型包裝類經常使用的值
add(int index, E element)
解釋:在list中指定位置插入指定的元素,若是當前位置有元素,就移動當前位置的元素
/** * 在list中指定位置插入指定的元素,若是當前位置有元素,就移動當前位置的元素 * 要插入的位置的後面全部元素的位置向前 + 1 * */ public void add(int index, E element) { // 檢查 0 這個位置是否越界 rangeCheckForAdd(index); // 再也不贅述,讀者能夠自行debug ensureCapacityInternal(size + 1); // Increments modCount!! // 由於從當前位置插入元素,因此當前位置及後面的元素都會向後移動 // 使用System.arraycopy 進行數組複製 System.arraycopy(elementData, index, elementData, index + 1, size - index); // 爲當前元素賦值 elementData[index] = element; size++; } /** * 爲add 和 addall 提供的範圍檢查, 不符合條件,拋出IndexOutOfBoundsException 異常 */ private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
Clear()
解釋:移除列表中的全部元素
/** * 移除list列表中全部的元素,列表會變爲空列表在調用此方法後 * */ public void clear() { // 修改次數 + 1 modCount++; // clear to let GC do its work // 把每一個變量置空,GC進行回收 for (int i = 0; i < size; i++) elementData[i] = null; // 列表的長度變爲0 size = 0; }
這個方法的源碼理解起來仍是比較簡單的
addAll(Collection<? extends E> c)
解釋: 把一個Collection集合添加到list末尾
/** * 把一個Collection集合(實現了此接口的類)添加到list的末尾,按着迭代的順序返回。 * 此操做的行爲是若是在此方法調用的過程當中修改了Collection(實現了此接口的類)的話, * 那麼這個操做不會成功 */ public boolean addAll(Collection<? extends E> c) { // 把Collection 轉換爲 Object[] 數組 Object[] a = c.toArray(); // 數組中有三個元素 int numNew = a.length; // 由於上面的操做調用了一次list.clear()方法,因此list.size = 0 ensureCapacityInternal(size + numNew); // Increments modCount // 一句話解釋: 把a 數組中0個位置的元素 複製到 elementData數組中 第size個位置的元素, // 複製的長度爲 numNew System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } // toArray()方法: /** * 返回一個數組,包含了全部的元素(從第一個元素到最後一個元素) * 返回的數組是很"安全的"由於列表沒有引用能夠維持(換句話說,這個方法必須分配一個新數組) * 調用者所以能夠任意修改返回的數組 * 這個方法是數組 和 集合之間的橋樑 */ public Object[] toArray() { return Arrays.copyOf(elementData, size); }
iterator(), hasNext(), next()
解釋:Iterator方法用於遍歷list中的元素,返回一個Itr 的內部類,hasNext()方法用於判斷list 中是否還有未遍歷的元素,next()方法用於獲取下一個元素
/** * 以適當的順序返回此列表中元素的迭代器 * 返回的iterator 支持fail-fast 機制 */ public Iterator<E> iterator() { return new Itr(); } /** * Itr 是一個內部類,實現了Iterator接口,可支持快速遍歷 */ private class Itr implements Iterator<E> { // 下一個元素返回的下標 int cursor; // index of next element to return // 最後一個元素返回的下標, 若是沒有返回-1 int lastRet = -1; // index of last element returned; -1 if no such // expectedModCount 指望的修改次數,默認是和modCount(修改次數相同,用於iterator判斷fail-fast機制) int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { // 判斷遍歷的過程當中是否觸發fail-fast機制 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() { // 若是lastRet < 0,說明 lastRet 沒有被改變, // 因此應該是沒有調用next()就調用了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++]); } cursor = i; lastRet = i - 1; checkForComodification(); } // 若是修改次數不知足預期修改次數的話,拋出異常 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
addAll(int index,Collection<? extends E> c)
解釋:在某個位置添加Collection集合
/** * 在指定的位置下標插入一個Collection集合 */ 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) // 第一次數組複製,從elementData中的index位置開始,複製到index + numNew位置上,複製numMoved個元素 System.arraycopy(elementData, index, elementData, index + numNew, numMoved); // 第二次數組複製,從a 數組中的第0個位置開始,複製到elementData第index位置上你,複製numNew個元素 System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; }
contains(Object o)
解釋:判斷list列表是否包含某個元素
/** * 返回true,若是這個列表包含指定的元素 * 更進一步來講,當且僅當list包含至少一個元素的狀況下,返回true */ public boolean contains(Object o) { return indexOf(o) >= 0; } /** * 返回列表中第一次出現指定元素的下標值,若是不包含指定元素,則返回-1。 * 更進一步來講,返回最小的索引當(o == null ? get(i) == null : o.equals(get(i)))的時候 * 或者返回-1 沒有此下標值 * */ public int indexOf(Object o) { // 若是o這個對象等於null,就判斷elementData中是否有空元素,若是有,返回 if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { // 若是不爲null,返回這個值的存儲位置 for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
remove(Object o)
解釋:移除list中的某個元素
/** * 若是存在,則移除list中某個第一次出現的元素。若是這個list不包含指定元素,就不會改變 * */ 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 }
indexOf(Object o)
解釋:檢索某個元素的位置
此源碼和contains(Object o)中調用的indexOf 源碼相同
subList(int fromIndex, int toIndex)
解釋:返回list列表的一個片斷
/** * 返回list列表中的一部分視圖(至關於list片斷),[fromIndex,toIndex),若是fromIndex 和 * toIndex 相同的話,代表這個list爲空,這個返回的list被返回,因此在list中並無結構的改變 * 這個返回的list片斷支持全部的list操做 */ public List<E> subList(int fromIndex, int toIndex) { // subList 範圍檢查 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 + ")"); } private class SubList extends AbstractList<E> implements RandomAccess { private final AbstractList<E> parent; private final int parentOffset; private final int offset; int size; 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; } }
ensureCapacity(int minCapacity)
解釋:擴大list的容量
/** * 增長ArrayList實例的容量,若是必須的話,確保它能持有最小容量的元素 */ public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // any size if not default element table ? 0 // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } }
trimToSize()
解釋:去掉list空閒的容量
/** * 去掉ArrayList中的多餘空間 */ public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } }
sort(Comparator<? super E> c)
sort 方法接收一個自定義比較器進行自定義比較,下面來看具體的源碼
@Override @SuppressWarnings("unchecked") public void sort(Comparator<? super E> c) { // 根據上面代碼分析,此時modCounnt 已經被修改過三次(添加了三個元素) final int expectedModCount = modCount; // 數組外部排序 Arrays.sort((E[]) elementData, 0, size, c); if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; }