【源码解析】ArrayList源码解析
生活随笔
收集整理的這篇文章主要介紹了
【源码解析】ArrayList源码解析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
存儲特性 – 有序且可重復
- 存儲元素,底層 Object 數據,數組不會對元素做判斷,所以可重復,基于數組下標的連續存儲,所以有序
- 數組容量一旦定義,就不能更改,可以擴容
初始容量 – 默認情況下,arrayList初始大小為 0
存儲滿后 – 擴容大小是原來的1.5倍
源碼add方法
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {// 版本號private static final long serialVersionUID = 8683452581122892189L;//設置arrayList默認容量 JDK1.6版本之前 10 1.6版本之后初始化大小為0private static final int DEFAULT_CAPACITY = 10;//空數組,當調用無參數構造函數的時候默認給個空數組private static final Object[] EMPTY_ELEMENTDATA = {};private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//這才是真正保存數據的數組private transient Object[] elementData;//arrayList的實際元素數量private int size;//構造方法傳入默認的capacity 設置默認數組大小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);}}// 無參數構造方法默認為空數組// 當前arrayList初始化構建的時候,底層的object數組長度為0public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}//構造方法傳入一個Collection, 則將Collection里面的值copy到arrayListpublic ArrayList(Collection<? extends E> c) {elementData = c.toArray();size = elementData.length;// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);}//下面主要看看ArrayList 是如何將數組進行動態擴充實現add 和 removepublic boolean add(E e) {// size + 1 計算當前存儲元素所需的數組最小長度ensureCapacityInternal(size + 1); // Increments modCount!!elementData[size++] = e;return true;}private void ensureCapacityInternal(int minCapacity) {// 第一次調用 calculateCapacity(elementData, minCapacity) = 10ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious code// elementData 空數組,長度0// 超出了數組可容納的長度,需要進行動態擴展if (minCapacity - elementData.length > 0)// arrayList擴容實現 minCapacity = 10grow(minCapacity);}// 傳遞 minCapacity = 10private void grow(int minCapacity) {// overflow-conscious code// 獲取數組原本長度int oldCapacity = elementData.length;// oldCapacity 右移一位,第一次執行,數組長度0,所以還是0// 不是第一次執行,oldCapacity >> 1 == 10(1010) >> 1 == 5(101)// 設置新數組的容量擴展為原來數組的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1);// 再判斷一下新數組的容量夠不夠,夠了就直接使用這個長度創建新數組,// 不夠就將數組長度設置為需要的長度// 只有第一次執行的時候才會進入if (newCapacity - minCapacity < 0)// 如果第一次執行,newCapacity = 0 minCapacity = 10 // 初始容量在此定義為 10newCapacity = minCapacity;//判斷有沒超過最大限制if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:// 將原來數組的值copy新數組中去, ArrayList的引用指向新數組// 這兒會新創建數組,如果數據量很大,重復的創建的數組,那么還是會影響效率,// 因此鼓勵在合適的時候通過構造方法指定默認的capaticy大小elementData = Arrays.copyOf(elementData, newCapacity);}public static <T> T[] copyOf(T[] original, int newLength) {return (T[]) copyOf(original, newLength, original.getClass());}public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;}private static int calculateCapacity(Object[] elementData, int minCapacity) {// 判斷 elementData 是否為空數組if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {// 只有第一次調用add方法才會進入// DEFAULT_CAPACITY = 10// minCapacity = 1// 調用max方法,返回 10return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}// a = 10 , b = 1 public static int max(int a, int b) {return (a >= b) ? a : b;}}源碼remove方法
public E remove(int index) {rangeCheck(index);modCount++;E oldValue = elementData(index);// 后面的每個值挨個前移一個位置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 workreturn oldValue;}總結
- arrayList 在JDK1.6之前默認長度10,1.6之后默認為 0
- 當用戶第一次調用add方法時,arrayList會進行第一次擴容,擴容后大小為 10
- arrayList在添加第11個元素的時候,會進行第二次擴容
- 迭代數組的時候,如果刪除數組元素,后面數組元素就會前移一個位置,所以就會引起并發修改異常,解決:
- 不使用迭代器,for循環即可
- CopyOnWriteArrayList 可讀寫的ArrayList
總結
以上是生活随笔為你收集整理的【源码解析】ArrayList源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Spring框架家族】Spring C
- 下一篇: 【全文搜索引擎】Elasticsearc