PS:若是以爲文章有什麼地方寫錯了,哪裏寫得很差,或者有什麼建議,歡迎指點。
ArrayList 類提供了 List ADT 的可增加數組的實現。java
源碼連接:戳此進GitHub查看git
MyArrayList 泛型類實現了 Iterable 接口從而能夠擁有加強 for 循環(for each 循環)。github
public class MyArrayList<AnyType> implements Iterable<AnyType> { @Override public Iterator<AnyType> iterator() { return new ArrayListIterator(); } }
MyArrayList 是基於數組實現的,其屬性有:算法
private static final int DEFAULT_CAPACITY = 10; private int theSize; private AnyType[] theArrays;
其中常量 DEFAULT_CAPACITY 表示數組的基礎容量。theSize 表示數組表當前長度(數組元素個數),做索引時,A[theSize - 1] 表示數組的最後一個元素,而 A[theSize] 表示新添加的項能夠被放置的位置。泛型數組 theArrays 爲 MyArrayList 類的數組實現,即對 MyArrayList 對象的操做實際爲對數組 theArrays 的操做。編程
當實例化 MyArrayList 對象時,調用構造方法:數組
public MyArrayList(){ theArrays = (AnyType[])new Object[DEFAULT_CAPACITY]; doClear(); }
在構造方法中先實例化泛型數組 theArrays。因爲泛型數組的建立是非法的,因此咱們須要建立一個泛型類型限界的數組;即建立一個 Object[] 類型的數組,而後向泛型類型數組 AnyType[] 強制轉型。ide
而後調用 doClear() 方法對數組表進行清空、初始化的操做,此方法僅類內部可調用:this
private void doClear(){ theSize = 0; expandCapacity(DEFAULT_CAPACITY); }
此處先設置 theSize = 0,而後調用 expandCapacity() 方法改變數組容量爲基礎容量。(在 expandCapacity() 方法的實現中,若擴充的容量(參數)小於 theSize 時表示非法的操做。)code
數組擴容方法 expandCapacity() :對象
public void expandCapacity(int newCapacity){ if (newCapacity < theSize){ return; } // 數組容量的擴充: AnyType[] newArrays = (AnyType[])new Object[newCapacity]; // 利用 System.arraycopy() 方法拷貝數組 System.arraycopy(theArrays,0,newArrays,0,theSize); theArrays = newArrays; }
System.arraycopy() 方法:
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
/** * 根據下標獲得數組元素的值 */ public AnyType get(int idx){ if (idx <0 || idx >= theSize){ throw new ArrayIndexOutOfBoundsException(); } return theArrays[idx]; }
/** * 根據下標設置數組元素的值 * 返回該下標元素的原值 */ public AnyType set(int idx,AnyType newVal){ if (idx <0 || idx >= theSize){ throw new ArrayIndexOutOfBoundsException(); } AnyType oldVal = theArrays[idx]; theArrays[idx] = newVal; return oldVal; }
/** * 根據下標向數組插入新元素 */ public boolean add(int idx,AnyType newVal){ // 當 idx=theSize 時,在 A[theSize] 位置處插入元素 if (idx < 0 || idx > theSize){ throw new ArrayIndexOutOfBoundsException(); } // 數組滿時擴充容量 if (theArrays.length == theSize){ expandCapacity(theSize*2 + 1); } // 數組元素後移 for (int i=theSize;i>idx;i--){ theArrays[i] = theArrays[i-1]; } theArrays[idx] = newVal; theSize++; return true; } /** * 在數組末尾插入新元素 */ public boolean add(AnyType newVal){ add(theSize,newVal); return true; }
/** * 根據下標刪除元素 * 返回被刪除的元素 */ public AnyType remove(int idx){ if (idx < 0 || idx >= theSize){ throw new ArrayIndexOutOfBoundsException(); } // 數組元素前移 AnyType removedElem = theArrays[idx]; for (int i = idx; i < theSize-1; i++) { theArrays[i] = theArrays[i+1]; } theSize--; return removedElem; }
實現 Iterable 接口的集合必須提供 iterator 方法,該方法返回一個 Iterator (java.util.Iterator)類型的對象:
public interface Iterator<AnyType> { boolean hasNext(); AnyType next(); void remove(); }
即每一個集合都可經過 iterator 方法建立並返回給客戶一個實現 Iterator 接口的對象,並把 當前位置 的概念在對象內部存儲下來。根據當前位置項每次調用 hasNext() 來判斷是否存在下一項,調用 next() 來給出下一項,而 remove() 方法則刪除由 next() 方法最新返回的項(即當調用一次 remove() 後,直到對 next() 再調用一次後才能調用 remove() 方法)。例:
public static <AnyType> void print(Collection<AnyType> coll){ Iterator<AnyType> itr = coll.iterator(); while(itr.hasNext()){ AnyType item = itr.next(); System.out.println(item); // itr.remove(); } }
Java 中的加強 for 循環(for each)底層便是經過這種迭代器模式來實現的,當使用加強 for 循環時也就是間接的使用 Iterator。
import java.util.Iterator; import java.util.NoSuchElementException; public class MyArrayList<AnyType> implements Iterable<AnyType> { ...... @Override public Iterator<AnyType> iterator() { return new ArrayListIterator(); } private class ArrayListIterator implements Iterator<AnyType>{ // 初始時當前位置爲 0 private int current = 0; @Override public boolean hasNext() { return current < theSize; } @Override public AnyType next() { if (!hasNext()){ throw new NoSuchElementException(); } return theArrays[current++]; } @Override public void remove() { /* 由於 remove() 方法有相同的,MyArrayList.this 表示外部類當前對象的一個引用 */ MyArrayList.this.remove(--current); } } }
iterator() 方法直接返回 ArrayListIterator 類的一個實例,該類是一個實現 Iterator 接口的類。ArrayListIterator 存儲當前位置的概念,並提供 hasNext()、next()、remove() 的實現。當前位置 表示要被查看的下一元素(的數組下標),所以初始化當前位置爲 0。
其中,泛型類 ArrayListIterator 是一個 內部類,使用內部類的目的及優勢:
由於 ArrayList 是基於數組實現的,因此和數組類似:ArrayList 的 get() 和 set() 方法花費常數時間 O(1);而使用 add() 和 remove() 方法時爲了保持內存數據的連續性,須要作大量的數據搬移工做,其花費的時間代價爲 O(n)。
歡迎您的點贊、收藏和評論!(完)