面試官Q1:可以手寫一個ArrayList的簡單實現嗎?
我們都知道ArrayList是基於數組實現,如果讓你實現JDK源碼ArrayList中add()、remove()、get()方法,你知道如何實現嗎?這一節,我們不看源碼,我們想想如何簡單的實現ArrayList幾個基本方法?
確定數據結構
我們知道,ArrayList中無論什么數據都能放,是不是意味着它是一個Object類型,既然是數組,那么是不是Object[]數組類型的?所以我們定義的數據結構如下:
private Object[] elementData; private int size;
設置自定義的MyArrayList的長度為10
public MyArrayList(){
this(10);
}
public MyArrayList(int initialCapacity){
if(initialCapacity<0){
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
elementData = new Object[initialCapacity];
}
有了存放數據的位置,接下來,我們想想如何將數據放入數組?
添加數據
public void add(Object obj){
elementData[size++]=obj;
}
每添加一個元素,size就會自增1,我們定義的數組長度為10,當我們添加到11個元素的時候,顯然沒有地方存放新添加的數據,這個時候我們需要對數組進行擴容處理對上面代碼做如下修改:
public void add(Object obj){
if(size==elementData.length){
//創建一個新的數組,並且這個數組的長度是原數組長度的2倍
Object[] newArray = new Object[size*2];
//使用底層拷貝,將原數組的內容拷貝到新數組
System.arraycopy(elementData, 0, newArray, 0, elementData.length);
//並將新數組賦值給原數組的引用
elementData = newArray;
}
//新來的元素,直接賦值
elementData[size++]=obj;
}
用一張圖來表示就是這樣的:
查詢數據
public Object get(int index){
return elementData[index];
}
刪除數據
接着我們看一下刪除的操作。ArrayList支持兩種刪除方式:
-
按照下標刪除
-
按照元素刪除,這會刪除ArrayList中與指定要刪除的元素匹配的第一個元素
對於ArrayList來說,這兩種刪除的方法差不多,都是調用的下面一段代碼:
public void remove(int index){
//刪除指定位置的對象
//a b d e
int numMoved = size - index - 1;
if (numMoved > 0){
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
}
elementData[--size] = null; // Let gc do its work
}
其實做的事情就是兩件:
-
把指定元素后面位置的所有元素,利用System.arraycopy方法整體向前移動一個位置
-
最后一個位置的元素指定為null,這樣讓gc可以去回收它
用圖表示是這樣的:

指定位置添加數據
把從指定位置開始的所有元素利用System,arraycopy方法做一個整體的復制,向后移動一個位置(當然先要用ensureCapacity方法進行判斷,加了一個元素之后數組會不會不夠大),然后指定位置的元素設置為需要插入的元素,完成了一次插入的操作。
public void add(int index,Object obj){
ensureCapacity(); //數組擴容
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = obj;
size++;
}
用圖表示這個過程是這樣的:
總結一下
從上面的幾個過程總結一下ArrayList的特點:
-
ArrayList底層以數組實現,是一種隨機訪問模式,通過下標索引定位數據,所以查找非常快
-
ArrayList在順序添加一個元素的時候非常方便,只是往數組里面添加了一個元素而已(這里指的末尾添加數據)
-
當刪除元素的時候,涉及到一次元素復制移位,如果要復制的元素很多,那么就會比較耗費性能
-
當插入元素的時候,涉及到一次元素復制移位,如果要復制的元素很多,那么就會比較耗費性能
因此,ArrayList比較適合順序添加、隨機訪問的場景。
