什么是Vector?
Vector是一個可以實現(xiàn)自動增長的對象數(shù)組(簡稱動態(tài)數(shù)組),可以隨著向量元素的增加而動態(tài)地增長,實際上是一種動態(tài)順序表的應(yīng)用
Vector與ArrayList有什么區(qū)別?
相同點
Vector:
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
}
ArrayList:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
}
可以看到 Vector 和 ArrayList 都繼承了 AbstractList 類,并且都實現(xiàn)了 List、RandomAccess、Cloneable、Serializable 接口,都可以存儲 null 值
不同點
這樣看來 Vector 和 ArrayLis 的功能是一樣的,那為什么會有 Vector 這個動態(tài)數(shù)組呢?ArrayList不也是動態(tài)數(shù)組嗎?因為 Vector 是基于線程安全的,而ArrayList不是線程安全的,所以有很多人都會說 Vector 是線程安全的 ArrayList
ArrayList默認的擴容倍數(shù)是1.5倍(關(guān)于ArrayList的擴容可以看下這篇文章 深入理解ArrayList),而Vector默認擴容的倍數(shù)是2倍
Vector中的一些成員變量
// 序列ID
private static final long serialVersionUID = 8683452581122892189L;
// 默認初始容量
private static final int DEFAULT_CAPACITY = 10;
// 用于空實例的共享空數(shù)組實例
private static final Object[] EMPTY_ELEMENTDATA = {};
// 共享的空數(shù)組實例,用于默認大小的空實例
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 存儲ArrayList元素的數(shù)組緩沖區(qū)
transient Object[] elementData; // non-private to simplify nested class access
// ArrayList的大小(其中包含的元素數(shù))
private int size;
Vector中的構(gòu)造方法有哪些?
一、Vector(int initialCapacity, int capacityIncrement)
// 創(chuàng)建輸入?yún)?shù)為初始化容量和增長量參數(shù)的構(gòu)造方法
public Vector(int initialCapacity, int capacityIncrement) {
super();
// 如果向量的初始化容量為負數(shù),則拋出 IllegalArgumentException 異常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
// 將初始化容量的長度作為Object數(shù)組(elementData)的實際長度
this.elementData = new Object[initialCapacity];
// 初始化增量參數(shù)
this.capacityIncrement = capacityIncrement;
}
二、Vector(int initialCapacity)
// 創(chuàng)建一個初始化容量且增量為0的數(shù)組
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
三、Vector()
// 創(chuàng)建一個初始化容量為10,且增量為0的空數(shù)組
public Vector() {
this(10);
}
四、Vector(Collection<? extends E> c)
// 創(chuàng)建一個包含指定集合中元素的數(shù)組,這些元素會按集合的迭代器返回元素的順序排列
public Vector(Collection<? extends E> c) {
// 將集合元素(c)轉(zhuǎn)換為數(shù)組并賦值給Object數(shù)組(elementData)
elementData = c.toArray();
// 獲取數(shù)組的長度
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
// 將c中的元素拷貝到Object數(shù)組(elementData)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
Vector的擴容
grow
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 傳入一個最小容量
private void grow(int minCapacity) {
// overflow-conscious code
// oldCapacity翻譯過來就是舊的容量,把Object數(shù)組(elementData)的長度賦值給舊的容量
int oldCapacity = elementData.length;
// newCapacity翻譯過來就是新的容量,當增量 > 0
// 那么新的容量就等于舊的容量+增量,否則為舊的容量的2倍(這里跟ArrayList中的不太一樣)
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
// 如果新的容量 - 實際需要的容量 < 0
if (newCapacity - minCapacity < 0)
// 將實際需要的容量賦值給新的容量
newCapacity = minCapacity;
// 如果新的容量比數(shù)組最大的容量還要大
if (newCapacity - MAX_ARRAY_SIZE > 0)
// 那么就擴容為巨大容量
newCapacity = hugeCapacity(minCapacity);
// 用Arrays.copyOf復(fù)制
elementData = Arrays.copyOf(elementData, newCapacity);
}
hugeCapacity()
巨大容量 hugeCapacity() 方法源碼如下(跟ArrayList的一樣):
private static int hugeCapacity(int minCapacity) {
// 如果傳入的實際容量 < 0,則拋出 OutOfMemoryError 異常
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
為了能更好的理解,我們把這段代碼搬過來運行測試一下:
/**
* 自己新建的類:測試 hugeCapacity 方法的作用
*/
public class HashDemo {
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
public static void main(String[] args) {
// 假設(shè)這里傳入10
int i = hugeCapacity(10);
System.out.println("Integer Max Value is " + Integer.MAX_VALUE);
System.out.println("hugeCapacity return is " + i);
}
}
輸出結(jié)果為:
可以看到 Integer的最大值為 2147483647,最大值 - 8 = 2147483639,也就是說不管我們傳入的數(shù)字是多少,經(jīng)過 hugeCapacity() 運算后得到的結(jié)果都是 最大值 - 8 = 2147483639
Integer Max Value is 2147483647
hugeCapacity return is 2147483639
我們再把傳入的數(shù)字改大一點,比如我們傳入一個比 最大值 - 8 = 2147483639 還要大的數(shù)字
public static void main(String[] args) {
// 假設(shè)這里傳入10
int i = hugeCapacity(2147483640);
System.out.println("Integer Max Value is " + Integer.MAX_VALUE);
System.out.println("hugeCapacity return is " + i);
}
輸出結(jié)果為:
可以看到當穿傳入的數(shù)字比 最大值 - 8 = 2147483639 還要大的數(shù)字的時候,返回的值就是 Integer 的最大值
Integer Max Value is 2147483647
hugeCapacity return is 2147483647
這樣講下來應(yīng)該比較好理解了
Vector中常用的操作
add()
// 采用同步的方式往向量中添加元素
public synchronized boolean add(E e) {
modCount++;
// 因為添加的元素需要動態(tài)地擴容,所以調(diào)用 ensureCapacityHelper 方法的時候需要 + 1
ensureCapacityHelper(elementCount + 1);
// 采用順序表添加元素,賦值長度+1
elementData[elementCount++] = e;
return true;
}
ensureCapacityHelper()
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
// 如果elementCount + 1 - 數(shù)組的容量 > 0
if (minCapacity - elementData.length > 0)
// 則進行擴容操作(上面已講解grow方法)
grow(minCapacity);
}
get()
// 返回向量中指定位置的元素
public synchronized E get(int index) {
// 如果下標 > 數(shù)組元素,則拋出 ArrayIndexOutOfBoundsException 異常
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
// 否則返回指定索引的對象
return elementData(index);
}
remove()
protected transient int modCount = 0;
public synchronized E remove(int index) {
// 修改次數(shù)+1
modCount++;
// 如果下標大于元素的數(shù)量,則拋出 ArrayIndexOutOfBoundsException 異常
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
// 使用下標獲取對應(yīng)的舊值
E oldValue = elementData(index);
// 計算刪除元素后需要移動補位的元素的數(shù)量
int numMoved = elementCount - index - 1;
// 如果這個數(shù)量 > 0
if (numMoved > 0)
// 拷貝元素
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 刪除元素
elementData[--elementCount] = null; // Let gc do its work
// 返回舊值
return oldValue;
}
為什么說Vector是線程安全的?
可以看到Vector的操作都是使用synchronized關(guān)鍵字進行同步的,也就是說是線程安全的,由于Vector是同步的,所以效率要比ArrayList低
Vector的簡單使用
創(chuàng)建一個Vector向量,添加元素
public class HashDemo {
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
vector.add("ArrayList");
vector.add("HashMap");
vector.add("ConcurrentHashMap");
vector.add("LinkedList");
vector.add("LinkedHashMap");
System.out.println(vector);
}
}
輸出結(jié)果為:
[ArrayList, HashMap, ConcurrentHashMap, LinkedList, LinkedHashMap]
使用迭代器輸出結(jié)果
public class HashDemo {
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
vector.add("ArrayList");
vector.add("HashMap");
vector.add("ConcurrentHashMap");
vector.add("LinkedList");
vector.add("LinkedHashMap");
Iterator<String> iterator = vector.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next()); // 這里一定要加上next(),不然會出現(xiàn)死循環(huán)
}
}
}
輸出結(jié)果為:
ArrayList
HashMap
ConcurrentHashMap
LinkedList
LinkedHashMap
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個個人學習交流的平臺,網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對此聲明的最終解釋權(quán)。