這一節(jié)我們來學(xué)習(xí)集合,什么是集合呢? 集合就如同數(shù)組,用來存儲和管理一組特定類型的數(shù)據(jù)對象,除了基本的數(shù)據(jù)處理功能,集合直接提供了各種數(shù)據(jù)結(jié)構(gòu)及算法的實現(xiàn),如隊列、鏈表、排序等,可以讓你輕易地完成復(fù)雜的數(shù)據(jù)操作。在使用數(shù)組和集合時要先加入system.collections命名空間,它提供了支持各種類型集合的接口及類。集合本身上也是一種類型,基本上可以將其作為用來存儲一組數(shù)據(jù)對象的容器,由于c#面向?qū)ο蟮奶匦?,管理?shù)據(jù)對象的集合同樣被實現(xiàn)成為對象,而存儲在集合中的數(shù)據(jù)對象則被稱為集合元素。這里提到了接口這個概念,它也是面向?qū)ο缶幊踢M化的重要標(biāo)準(zhǔn),我們在這里不做過多的講解,先注重學(xué)習(xí)集合中的對象及其使用就可以了,下面我們來學(xué)習(xí)第一種集合:
動態(tài)數(shù)組ArrayList.ArrayList類提供了繼承了IList接口。什么是繼承呢?這也是面向?qū)ο笳Z言的重要特點之一,現(xiàn)在你們先把它理解為,如果一個對象繼承了類或接口,那么它也具有了這個類和接口中的方法、屬性,可以用這些繼承的方法和屬性來做相應(yīng)的操作,比如:數(shù)組增加元素沒有Add()方法,但是動態(tài)數(shù)組ArrayList繼承了一個增加元素有Add()方法的接口,那么當(dāng)它要增加元素的時候,不僅可以用索引,也可以用繼承下來的Add()方法了。隨著學(xué)習(xí)的深入,我會給大家再具體講解繼承的概念和使用繼承的好處。那么下面讓我們來看看動態(tài)數(shù)組所繼承的這個接口IList它有什么特性呢?
Ilist接口:定義了利用索引訪問集合對象的方法,還繼承了ICollection和IEnumerable接口,除實現(xiàn)了接口原有的方法成員外,其本身也定義多個專門的方法成員,例如新增、移除、在指定位置插入元素或是返回特定元素在集合中所在的位置索引,這些方法主要為集合對象提供類似數(shù)組的元素訪問功能。
ILsit接口成員:add、insert、RemoveAt、Remove、contains、Clear、indexof方法,它最大的特色在于提供類似數(shù)組索引的訪問機制。
ArrayList對象是較為復(fù)雜的數(shù)組。我們可以將它看為擴充了功能的數(shù)組,但ArrayList并不等同于數(shù)組,與數(shù)組相比,它以下功能和區(qū)別是:
1. 數(shù)組的容量是固定的,但ArrayList的容量可以根據(jù)需要自動擴充。當(dāng)我們修改了ArrayList的容量時,則可以自動進行內(nèi)存重新分配和元素復(fù)制,比如往1號索引位插入n個元素,插入后,元素的索引依次向后n個位置排列,它是動態(tài)版本的數(shù)組類型。
2.ArrayList提供添加、插入或移除某一范圍元素的方法。但是在數(shù)組中,只能一次獲取或設(shè)置一個元素的值,如利用索引賦值。
3.ArrayList只有一維,而數(shù)組可以是多維。
4.ArrayList可以存放任何數(shù)據(jù)類型的數(shù)據(jù),而數(shù)組只能存儲同種數(shù)據(jù)類型的數(shù)據(jù)。
這種可以存放任何數(shù)據(jù)類型的機制,我們稱為裝箱,本節(jié)課的后半部分我會講解到,現(xiàn)在大家只需要記住,無論是什么數(shù)據(jù)類型,只要添加到動態(tài)數(shù)組中,都將轉(zhuǎn)變?yōu)镺bject數(shù)據(jù)類型,所以在遍歷Arraylist時,要定義一個Object類型的變量,用來接收遍歷它的每個項的值。
如何聲明一個動態(tài)數(shù)組呢?
ArrayList AL=new ArrayList( Capacity );//初始容量capacity也是可以不寫的
原因就是即使不在初識化確定容量,容量不夠的時候,會自動的按倍數(shù)作擴充。
接下來我們來看一下動態(tài)數(shù)組的常用屬性
Capacity 獲取或設(shè)置ArrayList可包含的元素數(shù)。
Count 獲取ArrayList中實際包含的元素數(shù)。
IsReadOnly 獲取一個值,該值表示ArrayList是否為只讀。
Item 獲取或設(shè)置指定索引處的元素。
動態(tài)數(shù)組的常用方法
增加元素-AL.Add(value);利用Add方法增加集合元素值
修改元素-AL[Index]=value;利用索引的方式修改元素的值
插入元素-AL.Insert(Index,value);將元素的值value,插入到第Index位置。
刪除元素-AL.Clear(); 全部刪除集合中的元素
AL.Remove(value);按照集合元素值刪除元素
AL.RemoveAt(Index);按照集合的元素索引刪除元素
縮減容量-AL.TrimToSize();將集合的容量減少到實際元素個數(shù)的大小
在執(zhí)行刪除操作后,要養(yǎng)成良好的縮減容量的習(xí)慣,節(jié)省內(nèi)存空間,提高性能。
查找元素-除了按數(shù)組的索引查找外,還可以用AL.Contains(value);按照元素值查找集合,如果包含便返回True,不包含時返回False。
得到類型--AL[index].GetType() 可以得到在index索引位的元素的數(shù)據(jù)類型
元素排序-- AL.Sort();
元素反轉(zhuǎn)-- AL.Reverse();
下面的例子我會給你們分部的演示出以上方法及屬性,運行結(jié)果我會用圖片的形式顯示出來,幫助你們理解動態(tài)數(shù)組是使用。
1 ArrayList AL = new ArrayList();
2 Console.WriteLine("容量: " + AL.Capacity);
3 Console.WriteLine("給動態(tài)數(shù)組添加元素:");
4 AL.Add("Hello");
5 Console.WriteLine("容量: " + AL.Capacity);
6 AL.Add(" World");
7 foreach (Object obj in AL)
8 {
9 Console.Write(obj);
10 }
11 Console.WriteLine();
12 Console.WriteLine("個數(shù):" + AL.Count);
13 Console.WriteLine("容量: " + AL.Capacity);
14 Console.WriteLine("第1個元素的數(shù)據(jù)類型為:" + AL[0].GetType());
1 AL.Insert(1, " c#");
2 Console.Write("在索引值為1的地方插入 ");
3 foreach (Object obj in AL)
4 { Console.Write(obj); }
5 Console.WriteLine();
6 Console.WriteLine("個數(shù):" + AL.Count);
7 Console.WriteLine("容量: " + AL.Capacity);
1 AL.Add("。");
2 Console.WriteLine("容量。: " + AL.Capacity);
3 AL.Add("---");
4 Console.WriteLine("容量---: " + AL.Capacity);
5
6 foreach (Object obj in AL)
7 { Console.Write(obj); }
2 Console.WriteLine("清除全部元素后:");
3 Console.WriteLine("個數(shù):" + AL.Count);
4 Console.WriteLine("容量: " + AL.Capacity);
通過以上的例子你們應(yīng)該已經(jīng)理解集合的方法,我們再來總結(jié)一下集合ArrayList相比數(shù)組有什么好處?主要是它可以根據(jù)使用大小按需動態(tài)增加,不用受事先設(shè)置大小的控制,還有就是可以隨意的添加、插入或移除某一范圍元素,比數(shù)組要方便。但是它也有不足,ArrayList 不管對象是什么類型都會添加到集合j中,在編譯時都是沒有問題的,但是在遍歷的時候,為防止集合中元素的類型不一致,所以最好使用object類型來接收遍歷j的元素,如foreach(object i in j)這樣就能減少錯誤,可能同學(xué)們會想,用object類型我們記住了,怎么就成弊端的呢?
這里我們就要學(xué)到另一個知識點,就是裝箱和拆箱。所謂裝箱就是把值類型打包成object引用類型的一個實例中,也就是說在進行裝箱的時候,必須分配并構(gòu)造一個全新的對象。而拆箱就是指從對象中提取值類型,將object類型強制轉(zhuǎn)換為原類型。
比如: ArrayList j=new ArrayList();
j.Add(123);
j.Add("123");
在添加時,ArrayList是會隱式的將整形的123 進行如下裝箱操作: int i=123; object o=(object)i;也就是說存進j的元素都將變成object類型
而在使用這個整形的123時,ArrayList又會進行如下的拆箱操作: o=123; i=(int)o; 也就是將o再強制轉(zhuǎn)換成原來的類型表現(xiàn)出去
想想這將是很大的性能消耗,需要進行大量的計算,至于怎么記住裝箱拆箱,我們就把這個過程想象成現(xiàn)實生活中,你買了很多中水果(元素),為了方便搬運,我們把他們都放到一個大盒子(集合對象)里,但是因為有榴蓮,我們又得把榴蓮(值類型元素)單獨包裝好(裝箱過程)再放到盒子里,到了家后,我們要打開盒子取出水果,在拿到榴蓮時,要想見到真正的榴蓮,我們就的把包裝去掉(拆箱),我們馬上就聞到了榴蓮那獨有的味道了(變回原類型)。哎!這個過程多麻煩呀!分了這么多步,在C#2.0出來后,就推出了新的技術(shù)來解決這個問題,那就是泛型,以后的章節(jié)我會講解這個新特性。
下面我們來講一下ArrayList向數(shù)組的互換。
例題:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11