vector

Java與C++語言中的對象

Vector類 是在 java 中可以實現自動增長的對象數組,vector在C++標準模板庫中的部分內容,它是一個多功能的,能夠操作多種數據結構和演演算法的模板類和函數庫。

詳細介紹


C中

vector是C++標準模板庫中的部分內容,中文偶爾譯作“容器”,但並不準確。它是一個多功能的,能夠操作多種數據結構和演演算法的模板類和函數庫。vector之所以被認為是一個容器,是因為它能夠像容器一樣存放各種類型的對象,簡單地說,vector是一個能夠存放任意類型的動態數組,能夠增加和壓縮數據。 
簡單的使用方法如下:
1
2
3
vectortest;test[1]就是2
我們可以用一個迭代器
vector::iterator iter=test.begin();//定義一個可以迭代int型vector的迭代器iter,它指向test的首位
for(;iter!=test.end();iter++) cout<<(*iter);//iter++指的是向後迭代一位,直到iter到超出末端迭代器為止,輸出迭代器指向的值
我們也可以使用at訪問:
1
2
3
4
vectortest;//建立一個vector
test.push_back(1);
test.push_back(2);//把1和2壓入vector這樣test[0]就是1,test[1]就是2
int i =test.at(1);//i為2

JAVA中

Java中Vector類是允許不同類型元素共存的變長數組Java.util.Vector提供了向量(Vector)類以實現類似動態數組的功能。在Java語言中是沒有指針概念的,但如果能正確靈活地使用指針又確實可以大大提高程序的質量,比如在C、C++中所謂“動態數組”一般都由指針來實現。為了彌補這點缺陷,Java提供了豐富的類庫來方便編程者使用,Vector類便是其中之一。事實上,靈活使用數組也可完成向量類的功能,向量類中提供的大量方法也大大方便了用戶的使用。 
在相對於ArrayList來說,Vector線程是安全的,也就是說是同步的。創建了一個向量類的對象后,可以往其中隨意地插入不同的類的對象,既不需顧及類型也不需預先選定向量的容量,並可方便地進行查找。對於預先不知或不願預先定義數組大小,並需頻繁進行查找、插入和刪除工作的情況,可以考慮使用向量類。向量類提供了三種構造方法: 
1
2
3
public Vector()
public Vector(int initialcapacity,int capacityIncrement)
public Vector(int initialcapacity)
使用第一種方法,系統會自動對向量對象進行管理。若使用后兩種方法,則系統將根據參數initialcapacity設定向量對象的容量(即向量對象可存儲數據的大小),當真正存放的數據個數超過容量時,系統會擴充向量對象的存儲容量。
參數capacityIncrement給定了每次擴充的擴充值。當capacityIncrement為0時,則每次擴充一倍。利用這個功能可以優化存儲。在Vector類中提供了各種方法方便用戶使用:

詳情介紹


vector 是同一種類型的對象的集合,每個對象都有一個對應的整數索引值。
string 對象一樣,標準庫將負責管理與存儲元素相關的內存。我們把 vector稱為容器,是因為它可以包含其他對象,能夠存放任意類型的動態數組,增加和壓縮數據。一個容器中的所有對象都必須是同一種類型的。
vector 是一個類模板(class template)。使用模板可以編寫一個類定義或函數定義,而用於多個不同的數據類型。因此,我們可以定義保存 string 對象的 vector,或保存 int 值得 vector,又或是保存自定義的類類型對象(如Sales_items 對象)的 vector。vector 不是一種數據類型,而只是一個模板,可用來定義任意多種數據類型。vector 類型的每一種都指定了其保存元素的類型。
為了可以使用vector,必須在你的頭文件中包含下面的代碼:
vector屬於std命名域的,因此需要通過命名限定,如下完成你的代碼:
1
2
using std::vector;
vector vInts;
或者連在一起,使用全名:
std::vector vInts;
建議在代碼量不大,並且使用的命名空間不多的情況下,使用全局的命名域方式:using namespace std函數。
(1)c.assign(beg,end) c.assign(n,elem)
將(beg; end)區間中的數據賦值給c。將n個elem的拷貝賦值給c。
傳回索引idx所指的數據,如果idx越界,拋出out_of_range
(2)c.back()
傳回最後一個數據,不檢查這個數據是否存在。
(3)c.begin()
傳回迭代器中的第一個數據地址。
(4)c.capacity()
返回容器當前已分配的容量。
(5)c.clear()
移除容器中所有數據。
(6)c.empty()
判斷容器是否為空。
c.end() //指向迭代器中末端元素的下一個,指向一個不存在元素。
c.erase(pos)// 刪除pos位置的數據,傳回下一個數據的位置。
c.erase(beg,end)
刪除[beg,end)區間的數據,傳回下一個數據的位置。
(7)c.front()
傳回第一個數據。
(8)get_allocator
使用構造函數返回一個拷貝。
c.insert(c.begin()+pos,elem)//在pos位置插入一個elem拷貝,傳回新數據位置
c.insert(c.begin()+pos,n,elem)//在pos位置插入n個elem數據,無返回值
c.insert(c.begin()+pos,beg,end)//在pos位置插入在[beg,end)區間的數據。無返回值
(9)c.max_size()
返回容器中最大數據的數量。
(10)c.pop_back()
刪除最後一個數據。
c.push_back(elem)
在尾部加入一個數據。
(11)c.rbegin()
傳回一個逆向隊列的第一個數據。
(12)c.rend()
傳回一個逆向隊列的最後一個數據的下一個位置。
(13)c.resize(num)
重新指定隊列的長度。
(14)c.reserve()
保留適當的容量。
(15)c.size()
返回容器中實際數據的個數。
c1.swap(c2)//將c1和c2元素互換
swap(c1,c2)//同上操作。
vector //創建一個空的vector
vector c1(c2)//複製一個vector
vector c(n)//創建一個vector,含有n個數據,數據均已預設構造產生
vector c(n,elem)//創建一個含有n個elem拷貝的vector
vector c(beg,end)//創建一個以(beg;end)為區間的vector
c.~ vector ()//銷毀所有數據,釋放內存
返回容器中指定位置的一個引用。
創建一個vector
vector容器提供了多種創建方法,下面介紹幾種常用的。
創建一個Widget類型的空的vector對象:
vector vWidgets;
創建一個包含500個Widget類型數據的vector:
vector vWidgets(500);
創建一個包含500個Widget類型數據的vector,並且都初始化為0:
vector vWidgets(500,Widget(0));
創建一個Widget的拷貝:
vector vWidgetsFromAnother(vWidgets);
向vector添加一個數據
vector添加數據的預設方法是push_back()。push_back()函數表示將數據添加到vector的尾部,並按需要來分配內存。例如:向vector;中添加10個數據,需要如下編寫代碼:
1
2
3
4
for(int i= 0;i<10; i++) 
{
vWidgets.push_back(Widget(i));
}
獲取vector中指定位置的數據。
vector裡面的數據是動態分配的,使用push_back()的一系列分配空間常常決定於文件或一些數據源。如果想知道vector是否為空,可以使用empty(),空返回true,否則返回false。獲取vector的大小,可以使用size()。例如,如果想獲取一個vector v的大小,但不知道它是否為空,或者已經包含了數據,如果為空時想設置為 -1,你可以使用下面的代碼實現:
int nSize = v.empty() ? -1 : static_cast(v.size());
訪問vector中的數據
使用兩種方法來訪問vector。
1、 vector::at()
2、 vector::operator[]
operator[]主要是為了與C語言進行兼容。它可以像C語言數組一樣操作。但at()是我們的首選,因為at()進行了邊界檢查,如果訪問超過了vector的範圍,將拋出一個例外。由於operator[]容易造成一些錯誤,所以我們很少用它.
刪除vector中的數據
vector能夠非常容易地添加數據,也能很方便地取出數據,同樣vector提供了erase(),pop_back(),clear()來刪除數據,當刪除數據時,應該知道要刪除尾部的數據,或者是刪除所有數據,還是個別的數據。
remove()演演算法 如果要使用remove,需要在頭文件中包含如下代碼:
#include
remove有三個參數:
1、 iterator _First:指向第一個數據的迭代指針。
2、 iterator _Last:指向最後一個數據的迭代指針。
3、 predicate _Pred:一個可以對迭代操作的條件函數。
條件函數
條件函數是一個按照用戶定義的條件返回是或否的結果,是最基本的函數指針,或是一個函數對象。這個函數對象需要支持所有的函數調用操作,重載operator()()操作。remove是通過unary_function繼承下來的,允許傳遞數據作為條件。
例如,假如想從一個vector;中刪除匹配的數據,如果字串中包含了一個值,從這個值開始,從這個值結束。首先應該建立一個數據結構來包含這些數據,類似代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include 
enum findmodes {
FM_INVALID = 0,
FM_IS,
FM_STARTSWITH,
FM_ENDSWITH,
FM_CONTAINS
};
typedef struct tagFindStr {
UINT iMode;
CString szMatchStr;
} FindStr;
typedef FindStr* LPFINDSTR;
然後處理條件判斷:
class FindMatchingString : public std::unary_functionbool> {
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;
}
LPFINDSTR m_lpFS;
};
通過這個操作你可以從vector中有效地刪除數據:
FindStr fs;
fs.iMode = FM_CONTAINS;
fs.szMatchStr = szRemove;
vs.erase(std::remove_if(vs.begin(),vs.end(),FindMatchingString(&fs)),vs.end());
Remove(),remove等所有的移出操作都是建立在一個迭代範圍上的,不能操作容器中的數據。所以在使用remove,實際上操作的是容器里數據的上面的。
看到remove實際上是根據條件對迭代地址進行了修改,在數據的後面存在一些殘餘的數據,那些需要刪除的數據。剩下的數據的位置可能不是原來的數據,但他們是不知道的。
調用erase()來刪除那些殘餘的數據。注意上面例子中通過erase()刪除remove的結果和vs.enc()範圍的數據。
常見錯誤:
no matching function for call to ‘std::vector,一般由定義的類型與存入的類型不匹配引起。

優點


Java中,數組對象一旦創建后,其元素的個數 不能被修改。而Java.util包中的Vector類(向量)提供類似於數組的能力,且能夠動態地調整自身的大小。Vector類似於一個數組,但與數組相比在使用上有兩個優點:
① 使用的時候無須聲明上限,隨著元素的增加,Vector的長度會自動增加;
② Vector類提供額外的方法來增加、刪除元素,比數組操作高效。 
插入功能
(1)public final synchronized void addElement(Object obj)
將obj插入向量的尾部。obj可以是任何類的對象。對同一個向量對象,可在其中插入不同類的對象。但插入的應是對象而不是數值,所以插入數值時要注意將數值轉換成相應的對象。
例 要插入一個整數1時,不要直接調用v1.addElement(1),正確的方法為:
1
2
3
Vectorv1=new Vector();
Integerinteger1=new Integer(1);
v1.addElement(integer1);
(2)public final synchronized void setElementAt(object obj,int index)
index處的對象設成obj,原來的對象將被覆蓋。
(3)public final synchronized void insertElementAt(Object obj,int index)
在index指定的位置插入obj,原來對象以及此後的對象依次往後順延。
(4)push_back()
在最後的位置添加元素(C++)
刪除功能
(1)public final synchronized void removeElement(Object obj)
從向量中刪除obj。若有多個存在,則從向量頭開始試,刪除找到的第一個與obj相同的向量成員。
(2)public final synchronized void removeAllElement()
刪除向量中所有的對象。
(3)public final synchronized void removeElementlAt(int index)
刪除index所指的地方的對象。
(4)pop_back()
刪除最後一個項(C++)
查詢搜索功能
(1)public final int indexOf(Object obj)
從向量頭開始搜索obj,返回所遇到的第一個obj對應的下標,若不存在此obj,返回-1。
(2)public final synchronized int indexOf(Object obj,int index)
從index所表示的下標處開始搜索obj。
(3)public final int lastIndexOf(Object obj)
從向量尾部開始逆向搜索obj。
(4)public final synchronized int lastIndexOf(Object obj,int index)
從index所表示的下標處由尾至頭逆向搜索obj。
(5)public final synchronized Object firstElement()
獲取向量對象中的首個obj。
(6)public final synchronized Object lastElement()
獲取向量對象中的最後一個obj。
實例
了解了向量的最基本的方法后,我們來看一下例子VectorApp.java。
例 VectorApp.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
importjava.util.Vector;
importjava.lang.*;
//這一句不應該要,但原文如此
importjava.util.Enumeration;
public class VectorApp
{
public static void main(String[]args)
{
Vector v1=new Vector();//jdk1.5以後增加了對的支持!
Integer integer1=new Integer(1);
//加入的為字元串對象
v1.addElement("one");
v1.addElement("two");
//加入的為Integer的對象
v1.addElement(integer1);
v1.addElement(newInteger(2));
System.out.println("Thevectorv1is:\n\t"+v1);
//此處的輸出結果為:Thevectorv1is:[1,2]
//將v1轉換成字元串並列印
v1.insertElementAt("three",2);
v1.insertElementAt(newFloat(3.9),3);
System.out.println("Thevectorv1(usedmethodinsertElementAt())is:\n\t"+v1);
//以上運行,請改Vector為Vector
//將指定位置的對象設置為新的對象
v1.setElementAt(2,1);
System.out.println("Thevectorv1(usedmethodsetElementAt())is:\n\t"+v1);
//從向量對象v1中刪除對象integer1由於存在多個integer1所以從頭開始找,刪除找到的第一個integer1
v1.removeElement(integer1);
//使用枚舉類(Enumeration)的方法來獲取向量對象的每個元素
Enumerationenum=v1.elements();
System.out.print("Thevectorv1(usedmethodremoveElement())is:");
while(enum.hasMoreElements())
System.out.print(enum.nextElement()+"");
System.out.println();
System.out.println("Thepositionofobject1(top-to-bottom):"
+v1.indexOf(integer1));
System.out.println("Thepositionofobject1(tottom-to-top):"
+v1.lastIndexOf(integer1));
//按不同的方向查找對象integer1所處的位置
v1.setSize(4);
System.out.println("Thenewvector(resizedthevector)is:"+v1);
//重新設置v1的大小,多餘的元素被行棄
}
}
運行結果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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中運行的結果中可以清楚地了解上面各種方法的作用,另外還有幾點需解釋。
(1)類Vector定義了方法
public final int size()
此方法用於獲取向量元素的個數。它的返回值是向量中實際存在的元素個數,而非向量容量。可以調用方法capactly()來獲取容量值。
方法:
public final synchronized void setsize(int newsize)
此方法用來定義向量大小。若向量對象現有成員個數已超過了newsize的值,則超過部分的多餘元素會丟失。
(2)程序中定義了Enumeration類的一個對象
Enumeration是java.util中的一個介面類,在Enumeration中封裝了有關枚舉數據集合的方法。
在Enumeration中提供了方法hasMoreElement()來判斷集合中是否還有其它元素和方法nextElement()來獲取下一個元素。利用這兩個方法可以依次獲得集合中元素。
Vector中提供方法:
public final synchronized Enumeration elements()
此方法將向量對象對應到一個枚舉類型。java.util包中的其它類中也大都有這類方法,以便於用戶獲取對應的枚舉類型。

缺點


時間

運行速度與數組相比較慢。

空間

clear()無法清空內存。