最近在看Vector與ArrayList的源碼,看下他們的區別與聯繫。數組
先看下他們的源碼是怎麼定義內部數據存儲的:安全
1 private static final long serialVersionUID = 8683452581122892189L; 2 3 /** 4 * Default initial capacity. 5 */ 6 private static final int DEFAULT_CAPACITY = 10; 7 8 /** 9 * Shared empty array instance used for empty instances. 10 */ 11 private static final Object[] EMPTY_ELEMENTDATA = {}; 12 13 /** 14 * The array buffer into which the elements of the ArrayList are stored. 15 * The capacity of the ArrayList is the length of this array buffer. Any 16 * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to 17 * DEFAULT_CAPACITY when the first element is added. 18 */ 19 private transient Object[] elementData; 20 21 /** 22 * The size of the ArrayList (the number of elements it contains). 23 * 24 * @serial 25 */ 26 private int size;
這是ArrayList的定義,他首先定義了他的初始化容量爲10less
private static final int DEFAULT_CAPACITY = 10
這裏應該看到了數據存儲是放在Object數組裏的函數
private transient Object[] elementData
定義了數據的長度size 大數據
The size of the ArrayList (the number of elements it contains)
再看看Vector的定義:this
1 /** 2 * The array buffer into which the components of the vector are 3 * stored. The capacity of the vector is the length of this array buffer, 4 * and is at least large enough to contain all the vector's elements. 5 * 6 * <p>Any array elements following the last element in the Vector are null. 7 * 8 * @serial 9 */ 10 protected Object[] elementData; 11 12 /** 13 * The number of valid components in this {@code Vector} object. 14 * Components {@code elementData[0]} through 15 * {@code elementData[elementCount-1]} are the actual items. 16 * 17 * @serial 18 */ 19 protected int elementCount; 20 21 /** 22 * The amount by which the capacity of the vector is automatically 23 * incremented when its size becomes greater than its capacity. If 24 * the capacity increment is less than or equal to zero, the capacity 25 * of the vector is doubled each time it needs to grow. 26 * 27 * @serial 28 */ 29 protected int capacityIncrement;
Vector定義了數組spa
protected Object[] elementData;
有效元素個數線程
protected int elementCount
Vector增加容量,默認0code
protected int capacityIncrement
Vector和ArrayList在元素超過初始大小時擴容是不同的,可是也不像網上說的Vector增加是按一倍增加,我以爲應該加默認兩個字纔對,Vector中的元素個數超過了初始化容量的話,默認確實會增加一倍,請看代碼:component
1 /** 2 * The maximum size of array to allocate. 3 * Some VMs reserve some header words in an array. 4 * Attempts to allocate larger arrays may result in 5 * OutOfMemoryError: Requested array size exceeds VM limit 6 */ 7 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 8 9 private void grow(int minCapacity) { 10 // overflow-conscious code 11 int oldCapacity = elementData.length; 12 int newCapacity = oldCapacity + ((capacityIncrement > 0) ? 13 capacityIncrement : oldCapacity); 14 if (newCapacity - minCapacity < 0) 15 newCapacity = minCapacity; 16 if (newCapacity - MAX_ARRAY_SIZE > 0) 17 newCapacity = hugeCapacity(minCapacity); 18 elementData = Arrays.copyOf(elementData, newCapacity); 19 }
代碼裏在判斷增加容量(簡稱增量)參數時若是增量大於0時,是會按增量進行擴容的,不然的話纔會增長一倍的容量到數組中。
而Vector在初始化加載構造函數時,開發人員是能夠指定其增量的大小的,並非必需要根據增長一倍的規則進行增長。仍是看代碼:
1 public Vector(int initialCapacity, int capacityIncrement) { 2 super(); 3 if (initialCapacity < 0) 4 throw new IllegalArgumentException("Illegal Capacity: "+ 5 initialCapacity); 6 this.elementData = new Object[initialCapacity]; 7 this.capacityIncrement = capacityIncrement; 8 } 9 10 /** 11 * Constructs an empty vector with the specified initial capacity and 12 * with its capacity increment equal to zero. 13 * 14 * @param initialCapacity the initial capacity of the vector 15 * @throws IllegalArgumentException if the specified initial capacity 16 * is negative 17 */ 18 public Vector(int initialCapacity) { 19 this(initialCapacity, 0); 20 } 21 22 /** 23 * Constructs an empty vector so that its internal data array 24 * has size {@code 10} and its standard capacity increment is 25 * zero. 26 */ 27 public Vector() { 28 this(10); 29 }
能夠看到在構造函數中已經代表,能夠指定其增量的大小,若是沒有指定默認0。數組的初始化大小爲10。
可是ArrayList就不能夠進行增量的修改指定。仍是看代碼:
1 /** 2 * Increases the capacity to ensure that it can hold at least the 3 * number of elements specified by the minimum capacity argument. 4 * 5 * @param minCapacity the desired minimum capacity 6 */ 7 private void grow(int minCapacity) { 8 // overflow-conscious code 9 int oldCapacity = elementData.length; 10 int newCapacity = oldCapacity + (oldCapacity >> 1); //看這裏 11 if (newCapacity - minCapacity < 0) 12 newCapacity = minCapacity; 13 if (newCapacity - MAX_ARRAY_SIZE > 0) 14 newCapacity = hugeCapacity(minCapacity); 15 // minCapacity is usually close to size, so this is a win: 16 elementData = Arrays.copyOf(elementData, newCapacity); 17 }
首先在構造函數中,ArrayList就沒有提供相應的設置增量的方法,而擴容方法grow中直接就對數組進行增量50%的操做了,並無相應的參數設置或判斷增量的大小。
在上邊都提到了一個靜態常量是private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
這個常量是數組擴容的最大長度,可是爲何-8呢我看了上邊的描述,感受應該是:
Some VMs reserve some header words in an array.
有些虛擬機會在數組頭部加入一些信息,若是仍是設置最大的話,可能會致使OOM
這就是Vector和ArrayList在擴容及成員變量方面的區別及聯繫了。
接下來咱們看看他們的源碼中插入、刪除等方法爲何說和LinkedList相比要慢
先看代碼:
1 public synchronized void insertElementAt(E obj, int index) { 2 modCount++; 3 if (index > elementCount) { 4 throw new ArrayIndexOutOfBoundsException(index 5 + " > " + elementCount); 6 } 7 ensureCapacityHelper(elementCount + 1); 8 System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); 9 elementData[index] = obj; 10 elementCount++; 11 }
Vector集合在add(int index, E element)時實際上調用了insertElementAt方法,他和刪除方法實際上都是對數組進行了copy,因此在大數據量時可能會致使效率下降。ArrayList也是這樣的狀況。
可是在增長調用add(E e)方法時,其實就是在數組中追加數據了,若是追加數據的長度大於實際數組長度的話,會進入到grow擴容方法進行擴容。
Vector和ArrayList都提供了trimToSize()方法,這個方法是對數組容量進行縮減的方法。在這個方法中,調用方法時會對數組的元素容量及數組自己長度進行判斷,若是數組內實際元素的個數比數組自己的長度少的話,調用這個方法會將數組縮減到元素個數大小。在數據量大的時候能夠考慮這樣作,這樣能夠節省沒必要要的空間浪費。看代碼:
1 public void trimToSize() { 2 modCount++; 3 if (size < elementData.length) { 4 elementData = Arrays.copyOf(elementData, size); 5 } 6 }
Vector自己提供了一個同步方法叫setSize方法,該方法能夠對當前集合進行長度設置。若是設置的長度比當前元素個數要大的話會進行判斷是否須要擴容,若是不是,在給定的Size值外的元素將被置爲空值。
看代碼:
1 public synchronized void setSize(int newSize) { 2 modCount++; 3 if (newSize > elementCount) { 4 ensureCapacityHelper(newSize); 5 } else { 6 for (int i = newSize ; i < elementCount ; i++) { 7 elementData[i] = null; 8 } 9 } 10 elementCount = newSize; 11 }
這大致上就是Vector和ArrayList的區別
ps:以上只是我的理解,若有不對請指正。