JAVA基礎整理(四)---手寫簡單的arraylist來學習arraylist

ArrayList類

經過自定義的arraylist類與jdk源碼裏的ArrayList的實現的對比學習:java

1.所需的變量:

private Object[] elementData;
private int size;
private static final int DEFAULT_LENGTH=10;
數組

private static final int DEFAULT_CAPACITY = 10;
transient Object[] elementData;
private int size;
函數

(1)默認長度設置成static final 由於這個是不隨具體對象改變的,是屬於類的通用不變屬性。學習

(2)爲何要把核心數組定義成 transient 數據類型,大概是由於序列化和反序列化的過程類要本身作,不要用默認的,至於緣由深刻後再談。測試

2.構造函數

1.無參構造this

public MyList(){code

elementData = new Object[DEALULT_LENGTH];

}
對象

public ArrayList() {ci

this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
element

無參構造能夠定義成static final ,不必每次都new一個新的空對象。

2.傳入length的構造

public MyList(int length){

elementData = new Object[length];

}

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);
}

}

對length進行判斷,大於0的狀況處理同樣的,等於0的話仍是調用了靜態的那個空對象,小於0拋出非法長度的異常。

3.增長元素

public void add(E obj){

Object[] newArray;
if(size == elementData.length) {
    newArray = new Object[elementData.length + (elementData.length >> 1)];
    System.arraycopy(elementData, 0, newArray, 0, elementData.length);
    elementData=newArray;
}
    elementData[size++]=obj;

}

public boolean add(E e) {

ensureCapacityInternal(size + 1);  // Increments modCount!!
elementData[size++] = e;
return true;

}

add的差異比較大,MyList的簡單邏輯:判斷目前存的size與elementData的長度的大小,若是size等於開的長度的話,再存進去會溢出,因此須要數組擴容,擴容的基本步驟:開一個新的數組,長度是原來的1.5倍(>>1就是加上了一半,這樣運算快點),將原來數組的東西拷貝到新數組的前面,將新數組指向elementData數組,把obj存進新數組裏。

源碼的邏輯多了幾層判斷,最終的擴容操做邏輯也是大同小異的:

private void grow(int minCapacity) {

// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
    newCapacity = minCapacity;
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);

}

4.刪除元素

public void remove(int index){

for(int i=index+1;i<elementData.length;i++){
   elementData[i-1] = elementData[i];
}
size--;

}

將index後的元素前移一位,size--;

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 work

return oldValue;

}

源碼裏remove後返回了刪除的值,而且多了一個rangecheck的函數進行index判斷,由於這個功能不少地方均可以用到,類似的。

private void rangeCheck(int index) {

if (index >= size)
    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

}

移動使用的是for循環,源碼使用了copy方法,作一個時間的測試:

5.修改元素

public void set(int index,E obj){

elementData[index]=obj;

}

public E set(int index, E element) {

rangeCheck(index);

E oldValue = elementData(index);
elementData[index] = element;
return oldValue;

}

也是多了一個rangecheck的判斷,而後返回了舊的的value。

<h4>6.查找元素</h4>

public E get(int index){

return (E)elementData[index];

}

public E get(int index) {

rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);

}

差異不大,就是返回elementdata的index元素。

相關文章
相關標籤/搜索