Java.util.Vector提供了向量(Vector)類以實(shí)現(xiàn)類似動(dòng)態(tài)數(shù)組的功能,。在Java語(yǔ)言中是沒(méi)有指針概念的,但如果能正確靈活地使用指針又確實(shí)可以大大提高程序的質(zhì)量,,比如在C,、C++中所謂“動(dòng)態(tài)數(shù)組”一般都由指針來(lái)實(shí)現(xiàn)。為了彌補(bǔ)這點(diǎn)缺陷,,Java提供了豐富的類庫(kù)來(lái)方便編程者使用,,Vector類便是其中之一。事實(shí)上,,靈活使用數(shù)組也可完成向量類的功能,,但向量類中提供的大量方法大大方便了用戶的使用。
相對(duì)于ArrayList來(lái)說(shuō),,Vector線程是安全的,也就是說(shuō)是同步的
創(chuàng)建了一個(gè)向量類的對(duì)象后,,可以往其中隨意地插入不同的類的對(duì)象,,既不需顧及類型也不需預(yù)先選定向量的容量,并可方便地進(jìn)行查找,。對(duì)于預(yù)先不知或不愿預(yù)先定義數(shù)組大小,,并需頻繁進(jìn)行查找、插入和刪除工作的情況,,可以考慮使用向量類,。向量類提供了三種構(gòu)造方法:
public vector()
public vector(int initialcapacity,int capacityIncrement)
public vector(int initialcapacity)
使用*種方法,系統(tǒng)會(huì)自動(dòng)對(duì)向量對(duì)象進(jìn)行管理,。若使用后兩種方法,,則系統(tǒng)將根據(jù)參數(shù)initialcapacity設(shè)定向量對(duì)象的容量(即向量對(duì)象可存儲(chǔ)數(shù)據(jù)的大小),,當(dāng)真正存放的數(shù)據(jù)個(gè)數(shù)超過(guò)容量時(shí),,系統(tǒng)會(huì)擴(kuò)充向量對(duì)象的存儲(chǔ)容量。
參數(shù)capacityIncrement給定了每次擴(kuò)充的擴(kuò)充值,。當(dāng)capacityIncrement為0時(shí),,則每次擴(kuò)充一倍,。利用這個(gè)功能可以優(yōu)化存儲(chǔ)。在Vector類中提供了各種方法方便用戶使用:
(1)public final synchronized void addElement(Object obj)
將obj插入向量的尾部,。obj可以是任何類的對(duì)象,。對(duì)同一個(gè)向量對(duì)象,可在其中插入不同類的對(duì)象,。但插入的應(yīng)是對(duì)象而不是數(shù)值,,所以插入數(shù)值時(shí)要注意將數(shù)值轉(zhuǎn)換成相應(yīng)的對(duì)象。
例 要插入一個(gè)整數(shù)1時(shí),,不要直接調(diào)用v1.addElement(1),,正確的方法為:
Vector v1=new Vector();
Integer integer1=new Integer(1);
v1.addElement(integer1);
(2)public final synchronized void setElementAt(object obj,int index)
將index處的對(duì)象設(shè)成obj,原來(lái)的對(duì)象將被復(fù)蓋,。
(3)public final synchronized void insertElementAt(Object obj,int index)
在index指定的位置插入obj,,原來(lái)對(duì)象以及此后的對(duì)象依次往后順延。
(1)public final synchronized void removeElement(Object obj)
從向量中刪除obj,。若有多個(gè)存在,,則從向量頭開(kāi)始試,刪除找到的*與obj相同的向量成員,。
(2)public final synchronized void removeAllElement()
刪除向量中所有的對(duì)象,。
(3)public final synchronized void removeElementlAt(int index)
刪除index所指的地方的對(duì)象。
(1)public final int indexOf(Object obj)
從向量頭開(kāi)始搜索obj,,返回所遇到的*obj對(duì)應(yīng)的下標(biāo),,若不存在此obj,返回-1,。
(2)public final synchronized int indexOf(Object obj,int index)
從index所表示的下標(biāo)處開(kāi)始搜索obj,。
(3)public final int lastIndexOf(Object obj)
從向量尾部開(kāi)始逆向搜索obj。
(4)public final synchronized int lastIndexOf(Object obj,int index)
從index所表示的下標(biāo)處由尾至頭逆向搜索obj,。
(5)public final synchronized Object firstElement()
獲取向量對(duì)象中的*obj,。
(6)public final synchronized Object lastelement()
獲取向量對(duì)象中的較后一個(gè)obj。
了解了向量的最基本的方法后,,我們來(lái)看一下例子VectorApp.java,。
例 VectorApp.java
import java.util.Vector;
import java.lang.*;
//這一句不應(yīng)該要,但原文如此
import java.util.Enumeration;
public class VectorApp
{
public static void main(String[] args)
{
Vector v1=new Vector();
Integer integer1=new Integer(1);
v1.addElement("one");
//加入的為字符串對(duì)象
v1.addElement(integer1);
v1.addElement(integer1);
//加入的為Integer的對(duì)象
v1.addElement("two");
v1.addElement(new Integer(2));
v1.addElement(integer1);
v1.addElement(integer1);
System.out.println("The vector v1 is:\n\t"+v1);
//將v1轉(zhuǎn)換成字符串并打印
v1.insertElementAt("three",2);
v1.insertElementAt(new Float(3.9),3);
System.out.println("The vector v1(used method insertElementAt())is:\n\t "+v1);
//往指定位置插入新的對(duì)象,,指定位置后的對(duì)象依次往后順延
v1.setElementAt("four",2);
System.out.println("The vector v1(used method setElementAt())is:\n\t "+v1);
//將指定位置的對(duì)象設(shè)置為新的對(duì)象
v1.removeElement(integer1);
//從向量對(duì)象v1中刪除對(duì)象integer1由于
存在多個(gè)integer1所以從頭開(kāi)始
找,,刪除找到的*integer1
Enumeration enum=v1.elements();
System.out.print("The vector v1(used method removeElement())is:");
while(enum.hasMoreElements())
System.out.print(enum.nextElement()+" ");
System.out.println();
//使用枚舉類(Enumeration)的方法來(lái)獲取向量對(duì)象的每個(gè)元素
System.out.println("The position of object 1(top-to-bottom):"
+ v1.indexOf(integer1));
System.out.println("The position of object 1(tottom-to-top):"
+v1.lastIndexOf(integer1));
//按不同的方向查找對(duì)象integer1所處的位置
v1.setSize(4);
System.out.println("The new vector(resized the vector)is:"+v1);
//重新設(shè)置v1的大小,多余的元素被行棄
}
}
運(yùn)行結(jié)果:
E:\java01>java VectorApp
The vector v1 is:
[one,1,1,two,2,1,1]
The vector v1(used method insertElementAt())is:
[one,1,three,3.9,1,two,2,1,1]
The vector v1(used method setElementAt()) is:
[one,1,four,3.9,1,two,2,1,1]
The vector v1(used method removeElement())is:
one four 3.9 1 two 2 1 1
The position of object 1(top-to-bottom):3
The position of object 1(tottom-to-top):7
The new vector(resized the vector)is:
[one,four,3.9,1]
E:\java01>
從例1中運(yùn)行的結(jié)果中可以清楚地了解上面各種方法的作用,,另外還有幾點(diǎn)需解釋,。
(1)類Vector定義了方法
public final int size()
此方法用于獲取向量元素的個(gè)數(shù)。它的返回值是向是中實(shí)際存在的元素個(gè)數(shù),,而非向量容量,�,?梢哉{(diào)用方法capactly()來(lái)獲取容量值。
方法:
public final synchronized void setsize(int newsize)
此方法用來(lái)定義向量大小,。若向量對(duì)象現(xiàn)有成員個(gè)數(shù)已超過(guò)了newsize的值,,則超過(guò)部分的多余元素會(huì)丟失。
(2)程序中定義了Enumeration類的一個(gè)對(duì)象
Enumeration是java.util中的一個(gè)接口類,,在Enumeration中封裝了有關(guān)枚舉數(shù)據(jù)集合的方法,。
在Enumeration中提供了方法hawMoreElement()來(lái)判斷集合中是否還有其它元素和方法nextElement()來(lái)獲取下一個(gè)元素。利用這兩個(gè)方法可以依次獲得集合中元素,。
Vector中提供方法:
public final synchronized Enumeration elements()
此方法將向量對(duì)象對(duì)應(yīng)到一個(gè)枚舉類型,。java.util包中的其它類中也大都有這類方法,以便于用戶獲取對(duì)應(yīng)的枚舉類型,。
vector 是同一種類型的對(duì)象的集合,每個(gè)對(duì)象都有一個(gè)對(duì)應(yīng)的整數(shù)索引值 ,。
和 string 對(duì)象一樣,標(biāo)準(zhǔn)庫(kù)將負(fù)責(zé)管理與存儲(chǔ)元素相關(guān)的內(nèi)存。我們把 vector稱為容器,是因?yàn)樗梢园渌麑?duì)象,,能夠存放任意類型的 動(dòng)態(tài)數(shù)組,,增加和壓縮數(shù)據(jù)。一個(gè)容器中的所有對(duì)象都必須是同一種類型的 ,。
vector 是一個(gè)類模板(class template),。使用模板可以編寫(xiě)一個(gè)類定義或函數(shù)定義,而用于多個(gè)不同的數(shù)據(jù)類型。因此,我們可以定義保存 string 對(duì)象的 vector,或保存 int 值的 vector,又或是保存自定義的類類型對(duì)象(如Sales_items 對(duì)象)的 vector,。vector 不是一種數(shù)據(jù)類型,而只是一個(gè)類模板,可用來(lái)定義任意多種數(shù)據(jù)類型,。vector 類型的每一種都指定了其保存元素的類型 。
為了可以使用vector,,必須在你的頭文件中包含下面的代碼:
#include <vector>
vector屬于 std命名 域的,,因此需要通過(guò)命名限定,如下完成你的代碼:
using std::vector;
vector<int> vInts;
或者連在一起,,使用全名:
std::vector<int> vInts;
建議在代碼量不大,并且使用的 命名空間不多的情況下,,使用全局的命名域方式: using namespace std;
函數(shù)
表述
c.assign(beg,end) c.assign(n,elem)
將(beg; end)區(qū)間中的數(shù)據(jù)賦值給c,。將n個(gè)elem的拷貝賦值給c。
傳回索引idx所指的數(shù)據(jù),,如果idx越界,,拋出out_of_range。
c.back()
傳回較后一個(gè)數(shù)據(jù),,不檢查這個(gè)數(shù)據(jù)是否存在,。
c.begin()
傳回 迭代器中的*數(shù)據(jù)地址。
c.capacity()
返回容器當(dāng)前已分配的容量,。
c.clear()
移除容器中所有數(shù)據(jù),。
c.empty()
判斷容器是否為空,。
c.end() //指向 迭代器中末端元素的下一個(gè),指向一個(gè)不存在元素,。
c.erase(pos)// 刪除pos位置的數(shù)據(jù),,傳回下一個(gè)數(shù)據(jù)的位置。
c.erase(beg,end)
刪除[beg,end)區(qū)間的數(shù)據(jù),,傳回下一個(gè)數(shù)據(jù)的位置,。
c.front()
傳回*數(shù)據(jù)。
get_allocator
使用 構(gòu)造函數(shù)返回一個(gè)拷貝,。
c.insert(pos,elem)//在pos位置插入一個(gè)elem拷貝,,傳回新數(shù)據(jù)位置
c.insert(pos,n,elem)//在pos位置插入n個(gè)elem數(shù)據(jù),無(wú)返回值
c.insert(pos,beg,end)//在pos位置插入在[beg,end)區(qū)間的數(shù)據(jù),。無(wú)返回值
c.max_size()
返回容器中*數(shù)據(jù)的數(shù)量,。
c.pop_back()
刪除較后一個(gè)數(shù)據(jù)。
c. push_back(elem)
在尾部加入一個(gè)數(shù)據(jù),。
c.rbegin()
傳回一個(gè)逆向隊(duì)列的*數(shù)據(jù),。
c.rend()
傳回一個(gè)逆向隊(duì)列的較后一個(gè)數(shù)據(jù)的下一個(gè)位置。
c.resize(num)
重新指定隊(duì)列的長(zhǎng)度,。
c.reserve()
保留適當(dāng)?shù)娜萘俊?/p>
c.size()
返回容器中實(shí)際數(shù)據(jù)的個(gè)數(shù),。
c1.swap(c2)//將c1和c2元素互換
swap(c1,c2)//同上操作。
vector<Elem> //創(chuàng)建一個(gè)空的vector
vector<Elem> c1(c2)//復(fù)制一個(gè)vector
vector <Elem> c(n)//創(chuàng)建一個(gè)vector,,含有n個(gè)數(shù)據(jù),,數(shù)據(jù)均已缺省構(gòu)造產(chǎn)生
vector <Elem> c(n,elem)//創(chuàng)建一個(gè)含有n個(gè)elem拷貝的vector
vector <Elem> c(beg,end)//創(chuàng)建一個(gè)以(beg;end)為區(qū)間的vector
c.~ vector operator[] 返回容器中指定位置的一個(gè)引用,。 創(chuàng)建一個(gè)vector vector容器提供了多種創(chuàng)建方法,,下面介紹幾種常用的。 創(chuàng)建一個(gè)Widget類型的空的vector對(duì)象: vector<Widget> vWidgets; 創(chuàng)建一個(gè)包含500個(gè)Widget類型數(shù)據(jù)的vector: vector<Widget> vWidgets(500); 創(chuàng)建一個(gè)包含500個(gè)Widget類型數(shù)據(jù)的vector,,并且都初始化為0: vector<Widget> vWidgets(500,Widget(0)); 創(chuàng)建一個(gè)Widget的拷貝: vector<Widget> vWidgetsFromAnother(vWidgets); 向vector添加一個(gè)數(shù)據(jù) vector添加數(shù)據(jù)的缺省方法是 push_back(),。 push_back()函數(shù)表示將數(shù)據(jù)添加到vector的尾部,并按需要來(lái)分配內(nèi)存,。例如: 向vector<Widget>,;中添加10個(gè)數(shù)據(jù),需要如下編寫(xiě)代碼: for(int i= 0;i<10; i++) { vWidgets. push_back(Widget(i)); } 獲取vector中指定位置的數(shù)據(jù) vector里面的數(shù)據(jù)是動(dòng)態(tài)分配的,,使用 push_back()的一系列分配空間常常決定于文件或一些數(shù)據(jù)源,。 如果想知道vector是否為空,可以使用empty(),,空返回true,,否則返回false。獲取vector的大小,,可以使用size(),。例如,,如果想獲取一個(gè)vector v的大小,但不知道它是否為空,,或者已經(jīng)包含了數(shù)據(jù),,如果為空時(shí)想設(shè)置為 -1,你可以使用下面的代碼實(shí)現(xiàn): int nSize = v.empty() ? -1 : static_cast<int>(v.size()); 訪問(wèn)vector中的數(shù)據(jù) 使用兩種方法來(lái)訪問(wèn)vector,。 1,、 vector::at() 2、 vector::operator[] operator[]主要是為了與C語(yǔ)言進(jìn)行兼容,。它可以像C語(yǔ)言 數(shù)組一樣操作,。但at()是我們的*,因?yàn)閍t()進(jìn)行了邊界檢查,,如果訪問(wèn)超過(guò)了vector的范圍,,將拋出一個(gè)例外。由于operator[]容易造成一些錯(cuò)誤,,所以我們很少用它. 刪除vector中的數(shù)據(jù) vector能夠非常容易地添加數(shù)據(jù),,也能很方便地取出數(shù)據(jù),同樣vector提供了erase(),,pop_back(),,clear()來(lái)刪除數(shù)據(jù),當(dāng)刪除數(shù)據(jù)時(shí),,應(yīng)該知道要?jiǎng)h除尾部的數(shù)據(jù),,或者是刪除所有數(shù)據(jù),還是個(gè)別的數(shù)據(jù),。 remove()算法 如果要使用remove,,需要在頭文件中包含如下代碼: #include <algorithm> remove有三個(gè)參數(shù): 1、 iterator _First:指向*數(shù)據(jù)的迭代 指針,。 2,、 iterator _Last:指向較后一個(gè)數(shù)據(jù)的迭代 指針。 3,、 predicate _Pred:一個(gè)可以對(duì) 迭代操作的條件函數(shù),。 條件函數(shù) 條件函數(shù)是一個(gè) 按照用戶定義的條件返回是或否的結(jié)果,是最基本的 函數(shù)指針,,或是一個(gè) 函數(shù)對(duì)象。這個(gè) 函數(shù)對(duì)象需要支持所有的 函數(shù)調(diào)用操作,, 重載operator()()操作,。remove是通過(guò)unary_function繼承下來(lái)的,允許傳遞數(shù)據(jù)作為條件,。 例如,,假如想從一個(gè)vector<CString>,;中刪除匹配的數(shù)據(jù),如果字串中包含了一個(gè)值,,從這個(gè)值開(kāi)始,,從這個(gè)值結(jié)束。首先應(yīng)該建立一個(gè) 數(shù)據(jù)結(jié)構(gòu)來(lái)包含這些數(shù)據(jù),,類似代碼如下: #include <functional> enum findmodes { FM_INVALID = 0, FM_IS, FM_STARTSWITH, FM_ENDSWITH, FM_CONTAINS }; typedef struct tagFindStr { UINT iMode; CString szMatchStr; } FindStr; typedef FindStr* LPFINDSTR; 然后處理?xiàng)l件判斷: class FindMatchingString : public std::unary_function<CString,bool> { public: FindMatchingString(const LPFINDSTR lpFS) : m_lpFS(lpFS) { } bool operator()(CString& szStringToCompare) const { bool retVal = false; switch (m_lpFS->iMode) { case FM_IS: { retVal = (szStringToCompare == m_lpFDD->szMatchStr); break; } case FM_STARTSWITH: { retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength()) == m_lpFDD->szWindowTitle); break; } case FM_ENDSWITH: { retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength()) == m_lpFDD->szMatchStr); break; } case FM_CONTAINS: { retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1); break; } } return retVal; } private: LPFINDSTR m_lpFS; }; 通過(guò)這個(gè)操作你可以從vector中有效地刪除數(shù)據(jù): FindStr fs; fs.iMode = FM_CONTAINS; fs.szMatchStr = szRemove; vs.erase(std::remove_if(vs.begin(),vs.end(),FindMatchingString(&fs)),vs.end()); Remove(),remove等所有的移出操作都是建立在一個(gè)迭代范圍上的,,不能操作容器中的數(shù)據(jù)。所以在使用remove,,實(shí)際上操作的時(shí)容器里數(shù)據(jù)的上面的,。 看到remove實(shí)際上是根據(jù)條件對(duì) 迭代地址進(jìn)行了修改,在數(shù)據(jù)的后面存在一些殘余的數(shù)據(jù),,那些需要?jiǎng)h除的數(shù)據(jù),。剩下的數(shù)據(jù)的位置可能不是原來(lái)的數(shù)據(jù),但他們是不知道的,。 調(diào)用erase()來(lái)刪除那些殘余的數(shù)據(jù),。注意上面例子中通過(guò)erase()刪除remove的結(jié)果和vs.enc()范圍的數(shù)據(jù)。 常見(jiàn)錯(cuò)誤: no matching function for call to ‘std::vector,,一般由定義的類型與存入的 類型不匹配引起,。