Vector可以實(shí)現(xiàn)可增長的對(duì)象數(shù)組拌喉。與數(shù)組一樣派诬,它包含可以使用整數(shù)索引進(jìn)行訪問的組件盟萨。不過吝羞,Vector的大小是可以增加或者減小的兰伤,以便適應(yīng)創(chuàng)建Vector后進(jìn)行添加或者刪除操作。
Vector實(shí)現(xiàn)List接口钧排,繼承AbstractList類敦腔,所以我們可以將其看做隊(duì)列,支持相關(guān)的添加恨溜、刪除符衔、修改找前、遍歷等功能。
/**
* 構(gòu)造一個(gè)空向量判族,使其內(nèi)部數(shù)據(jù)數(shù)組的大小為 10纸厉,其標(biāo)準(zhǔn)容量增量為零。
*/
public Vector() {
this(10);
}
/**
* 構(gòu)造一個(gè)包含指定 collection 中的元素的向量五嫂,這些元素按其 collection 的迭代器返回元素的順序排列。
*/
public Vector(Collection<? extends E> c) {
elementData = c.toArray();
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount,
Object[].class);
}
/**
* 使用指定的初始容量和等于零的容量增量構(gòu)造一個(gè)空向量肯尺。
*/
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
/**
* 使用指定的初始容量和容量增量構(gòu)造一個(gè)空的向量沃缘。
*/
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
在成員變量方面,Vector提供了elementData , elementCount则吟, capacityIncrement三個(gè)成員變量槐臀。其中
elementData :”O(jiān)bject[]類型的數(shù)組”,它保存了Vector中的元素氓仲。按照Vector的設(shè)計(jì)elementData為一個(gè)動(dòng)態(tài)數(shù)組水慨,可以隨著元素的增加而動(dòng)態(tài)的增長,其具體的增加方式后面提到(ensureCapacity方法)敬扛。如果在初始化Vector時(shí)沒有指定容器大小晰洒,則使用默認(rèn)大小為10.
elementCount:Vector 對(duì)象中的有效組件數(shù)。
capacityIncrement:向量的大小大于其容量時(shí)啥箭,容量自動(dòng)增加的量谍珊。如果在創(chuàng)建Vector時(shí),指定了capacityIncrement的大屑苯摹砌滞;則,每次當(dāng)Vector中動(dòng)態(tài)數(shù)組容量增加時(shí)>坏怪,增加的大小都是capacityIncrement贝润。如果容量的增量小于等于零,則每次需要增大容量時(shí)铝宵,向量的容量將增大一倍打掘。
同時(shí)Vector是線程安全的!
add(E e)
將指定元素添加到此向量的末尾鹏秋。
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1); //確認(rèn)容器大小胧卤,如果操作容量則擴(kuò)容操作
elementData[elementCount++] = e; //將e元素添加至末尾
return true;
}
這個(gè)方法相對(duì)而言比較簡單,具體過程就是先確認(rèn)容器的大小拼岳,看是否需要進(jìn)行擴(kuò)容操作枝誊,然后將E元素添加到此向量的末尾。
private void ensureCapacityHelper(int minCapacity) {
//如果
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 進(jìn)行擴(kuò)容操作
* 如果此向量的當(dāng)前容量小于minCapacity惜纸,則通過將其內(nèi)部數(shù)組替換為一個(gè)較大的數(shù)組倆增加其容量叶撒。
* 新數(shù)據(jù)數(shù)組的大小姜維原來的大小 + capacityIncrement绝骚,
* 除非 capacityIncrement 的值小于等于零,在后一種情況下祠够,新的容量將為原來容量的兩倍压汪,不過,如果此大小仍然小于 minCapacity古瓤,則新容量將為 minCapacity止剖。
*/
private void grow(int minCapacity) {
int oldCapacity = elementData.length; //當(dāng)前容器大小
/*
* 新容器大小
* 若容量增量系數(shù)(capacityIncrement) > 0,則將容器大小增加到capacityIncrement
* 否則將容量增加一倍
*/
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
/**
* 判斷是否超出最大范圍
* MAX_ARRAY_SIZE:private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
*/
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
對(duì)于Vector整個(gè)的擴(kuò)容過程落君,就是根據(jù)capacityIncrement確認(rèn)擴(kuò)容大小的穿香,若capacityIncrement <= 0 則擴(kuò)大一倍,否則擴(kuò)大至capacityIncrement 绎速。當(dāng)然這個(gè)容量的最大范圍為Integer.MAX_VALUE即皮获,2^32 – 1,所以Vector并不是可以無限擴(kuò)充的纹冤。
remove(Object o)
/**
* 從Vector容器中移除指定元素E
*/
public boolean remove(Object o) {
return removeElement(o);
}
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj); //計(jì)算obj在Vector容器中位置
if (i >= 0) {
removeElementAt(i); //移除
return true;
}
return false;
}
public synchronized void removeElementAt(int index) {
modCount++; //修改次數(shù)+1
if (index >= elementCount) { //刪除位置大于容器有效大小
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
else if (index < 0) { //位置小于 < 0
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
//從指定源數(shù)組中復(fù)制一個(gè)數(shù)組洒宝,復(fù)制從指定的位置開始,到目標(biāo)數(shù)組的指定位置結(jié)束萌京。
//也就是數(shù)組元素從j位置往前移
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--; //容器中有效組件個(gè)數(shù) - 1
elementData[elementCount] = null; //將向量的末尾位置設(shè)置為null
}
因?yàn)閂ector底層是使用數(shù)組實(shí)現(xiàn)的雁歌,所以它的操作都是對(duì)數(shù)組進(jìn)行操作,只不過其是可以隨著元素的增加而動(dòng)態(tài)的改變?nèi)萘看笮≈校鋵?shí)現(xiàn)方法是是使用Arrays.copyOf方法將舊數(shù)據(jù)拷貝到一個(gè)新的大容量數(shù)組中将宪。Vector的整個(gè)內(nèi)部實(shí)現(xiàn)都比較簡單,這里就不在重述了橡庞。
Vector遍歷
Vector支持4種遍歷方式较坛。
因?yàn)閂ector實(shí)現(xiàn)了RandmoAccess接口,可以通過下標(biāo)來進(jìn)行隨機(jī)訪問扒最。
for(int i = 0 ; i < vec.size() ; i++){
value = vec.get(i);
}
迭代器
Iterator it = vec.iterator();
while(it.hasNext()){
value = it.next();
//do something
}
for循環(huán)(語法糖 本質(zhì)上也是迭代器)
for(Integer value:vec){
//do something
}
Enumeration循環(huán)
Vector vec = new Vector<>();
Enumeration enu = vec.elements();
while (enu.hasMoreElements()) {
value = (Integer)enu.nextElement();
}
Stack
在Java中Stack類表示后進(jìn)先出(LIFO)的對(duì)象堆棧丑勤。棧是一種非常常見的數(shù)據(jù)結(jié)構(gòu),它采用典型的先進(jìn)后出的操作方式完成的吧趣。每一個(gè)棧都包含一個(gè)棧頂法竞,每次出棧是將棧頂?shù)臄?shù)據(jù)取出,如下:
Stack通過五個(gè)操作對(duì)Vector進(jìn)行擴(kuò)展强挫,允許將向量視為堆棧岔霸。這個(gè)五個(gè)操作如下:
Stack繼承Vector,他對(duì)Vector進(jìn)行了簡單的擴(kuò)展:
public class Stack<E> extends Vector<E>
Stack的實(shí)現(xiàn)非常簡單俯渤,僅有一個(gè)構(gòu)造方法呆细,五個(gè)實(shí)現(xiàn)方法(從Vector繼承而來的方法不算與其中),同時(shí)其實(shí)現(xiàn)的源碼非常簡單
/**
* 構(gòu)造函數(shù)
*/
public Stack() {
}
/**
* push函數(shù):將元素存入棧頂
*/
public E push(E item) {
// 將元素存入棧頂八匠。
// addElement()的實(shí)現(xiàn)在Vector.java中
addElement(item);
return item;
}
/**
* pop函數(shù):返回棧頂元素絮爷,并將其從棧中刪除
*/
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
// 刪除棧頂元素趴酣,removeElementAt()的實(shí)現(xiàn)在Vector.java中
removeElementAt(len - 1);
return obj;
}
/**
* peek函數(shù):返回棧頂元素,不執(zhí)行刪除操作
*/
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
// 返回棧頂元素坑夯,elementAt()具體實(shí)現(xiàn)在Vector.java中
return elementAt(len - 1);
}
/**
* 棧是否為空
*/
public boolean empty() {
return size() == 0;
}
/**
* 查找“元素o”在棧中的位置:由棧底向棧頂方向數(shù)
*/
public synchronized int search(Object o) {
// 獲取元素索引岖寞,elementAt()具體實(shí)現(xiàn)在Vector.java中
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}