作者:兵小志大

鏈接:www.cnblogs.com/try-better-tomorrow

1.概述

關於Java集合小抄中的描述:

http://calvin1978.blogcn.com/articles/collection.html

以數組實現。節約空間,但數組有容量限制。超出限制時會增加50%容量,用System.arraycopy()複製到新的數組,因此最好能給出數組大小的預估值。默認第一次插入元素時創建大小爲10的數組。

按數組下標訪問元素—get(i)/set(i,e) 的性能很高,這是數組的基本優勢。

直接在數組末尾加入元素—add(e)的性能也高,但如果按下標插入、刪除元素—add(i,e), remove(i), remove(e),則要用System.arraycopy()來移動部分受影響的元素,性能就變差了,這是基本劣勢。

然後再來學習一下官方文檔:

Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List interface, this class provides methods to manipulate the size of the array that is used internally to store the list. (This class is roughly equivalent to Vector, except that it is unsynchronized.)

ArrayList是一個相對來說比較簡單的數據結構,最重要的一點就是它的自動擴容,可以認爲就是我們常說的“動態數組”。

來看一段簡單的代碼:

ArrayList list = new ArrayList();

list.add("語文: 99");

list.add("數學: 98");

list.add("英語: 100");

list.remove(0);

在執行這四條語句時,是這麼變化的:

Java ArrayList 工作原理及實現

其中,add操作可以理解爲直接將數組的內容置位,remove操作可以理解爲刪除index爲0的節點,並將後面元素移到0處。

2. add函數

當我們在ArrayList中增加元素的時候,會使用add函數。他會將元素放到末尾。具體實現如下:

public boolean add(E e) {

ensureCapacityInternal(size + 1); // Increments modCount!!

elementData[size++] = e;

return true;

}

我們可以看到他的實現其實最核心的內容就是ensureCapacityInternal。這個函數其實就是自動擴容機制的核心。我們依次來看一下他的具體實現

private void ensureCapacityInternal(int minCapacity) {

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);

}

ensureExplicitCapacity(minCapacity);

}

private void ensureExplicitCapacity(int minCapacity) {

modCount++;

// overflow-conscious code

if (minCapacity - elementData.length > 0)

grow(minCapacity);

}

private void grow(int minCapacity) {

// overflow-conscious code

int oldCapacity = elementData.length;

// 擴展爲原來的1.5倍

int newCapacity = oldCapacity + (oldCapacity >> 1);

// 如果擴爲1.5倍還不滿足需求,直接擴爲需求值

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

}

也就是說,當增加數據的時候,如果ArrayList的大小已經不滿足需求時,那麼就將數組變爲原長度的1.5倍,之後的操作就是把老的數組拷到新的數組裏面。

例如,默認的數組大小是10,也就是說當我們add10個元素之後,再進行一次add時,就會發生自動擴容,數組長度由10變爲了15具體情況如下所示:

Java ArrayList 工作原理及實現

3.set和get函數

Array的put和get函數就比較簡單了,先做index檢查,然後執行賦值或訪問操作:

public E set(int index, E element) {

rangeCheck(index);

E oldValue = elementData(index);

elementData[index] = element;

return oldValue;

}

public E get(int index) {

rangeCheck(index);

return elementData(index);

}

4.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);

// 把最後的置null

elementData[--size] = null; // clear to let GC do its work

return oldValue;

}

註釋很清楚:

Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).

相關文章