1 System.Collections命名空間
System.Collections命名空間包含可使用的集合類和相關的接口。該命名空間下的.NET非泛型集合類如下所示。
— System.Collections.ArrayList:數組集合類
— System.Collections.BitArray:布爾集合類
— System.Collections.Queue:隊列
— System.Collections.Stack:堆棧
— System.Collections.Hashtable:哈希表
— System.Collections.SortedList:排序集合類
注意:本章的示例性代碼都在using區添加了System.Collections。
2 ArrayList數組集合類
ArrayList類可以視作是Array與Collection對象的結合。該類既有數組的特徵又有集合的特性,例如,既可以通過下標進行元素訪問,對元素排序、搜索,又可以像處理集合一樣添加、在指定索引插入及刪除元素。
由於ArrayList中元素的類型默認爲object類型,因此,在獲取集合元素時需要進行強制類型轉換。並且object是引用類型,在與值類型進行轉換時,會引起裝箱和拆箱的操作,需要付出一些性能代價。
2.1 創建列表
爲了創建ArrayList,可以使用三種重載構造函數中的一種,還可以使用ArrayList的靜態方法Repeat創建一個新的ArrayList。這三個構造函數的聲明如下。
//使用默認的初始容量創建ArrayList,該實例並沒有任何元素
public ArrayList();
//使用實現了ICollection接口的集合類來初始化新創建的ArrayList
public ArrayList(ICollection c);
//經由指定一個整數值來初始化ArrayList的容量
public ArrayList(int capacity);
//下面的例子代碼演示了使用4種創建ArrayList的方法。
static void Main(string[] args)
{
//使用默認的初始容量創建ArrayList,該實例並沒有任何元素
ArrayList al1 = new ArrayList();
al1.Add("111");
al1.Add("222");
al1.Add("333");
DisplayResult(al1);
//使用實現了ICollection接口的集合類來初始化新創建的ArrayList,該實例與參數中的集合具有相同的初始容量
ArrayList al2 = new ArrayList(al1);
//調用顯示結果子程序
DisplayResult(al2);
//經由指定一個整數值來初始化ArrayList的容量
ArrayList al3 = new ArrayList(20);
DisplayResult(al3);
//將指定ccc字符串重複4次構造數組
ArrayList al4=ArrayList.Repeat("ccc", 4);
DisplayResult(al4);
Console.ReadLine();
}
//在控制檯窗口顯示數組的內容
static void DisplayResult(ArrayList ls)
{
Console.WriteLine("");
if (ls.Count <= 0)
{
Console.WriteLine("數組沒有任何集合元素");
}
foreach (object s in ls)
{
Console.Write(Convert.ToString(s));
}
}
//注意:爲了實現上面的例子,必須在using區添加System.Collections命名空間。
2.2 添加元素
有兩種方法可用於向ArrayList添加元素:Add和AddRange。
— Add方法將單個元素添加到列表的尾部。
— AddRange方法獲取一個實現ICollection接口的集合實例,例如Array、Queue、Stack等,並將這個集合實例按順序添加到列表的尾部。
這兩個方法的聲明如下。
//參數:value:需要添加到ArrayList中的值
public virtual int Add(object value);
//參數:c:實現了ICollection的集合類
public virtual void AddRange(ICollection c);
//注意:ArrayList接受null值並且允許元素重複。
//下面代碼演示瞭如何添加集合元素。
static void Main(string[] args)
{
//聲明一個接受20個元素的ArrayList
ArrayList al = new ArrayList(20);
//使用ArrayList的Add方法添加集合元素
al.Add("我是元素一");
al.Add("我是元素二");
al.Add("我是元素三");
al.Add("我是元素四");
string[] strs ={ "我是元素五", "我是元素六", "我是元素七", "我是元素八" };
//使用AddRange方法添加實現了ICollections接口的集,並按集合參數中元素的順序添加
al.AddRange(strs);
foreach (string str in al)
{
Console.WriteLine(str);
}
Console.ReadLine();
}
2.3 插入元素
插入元素也是向集合中增加元素,與添加(Add或AddRange)元素不同的是,插入元素可以指定要插入的位置的索引,而添加只能在集合的尾部順序添加。插入元素也有兩種方法:Insert和InsertRange。
— Insert方法添加單個元素到指定的索引位置。
— InsertRange從指定的位置開始添加一個實現了ICollection接口的實例。
這兩個方法的聲明如下所示。
//在指定的索引位置index中添加單個元素值value
public virtual void Insert(int index, object value);
//在指定的索引位置index處添加實現了ICollection接口的集合實例
public virtual void InsertRange(int index, ICollection c);
//下面的示例代碼演示了插入集合元素的方法。
static void Main(string[] args)
{
ArrayList al = new ArrayList(20);
//使用Insert方法插入集合元素
al.Insert(0, "我是元素一");
al.Insert(1, "我是元素二");
al.Insert(2, "我是元素三");
al.Insert(3, "我是元素四");
Queue qu=new Queue();
qu.Enqueue("我是元素五");
qu.Enqueue("我是元素六");
qu.Enqueue("我是元素七");
//使用InsertRange方法插入集合元素
al.InsertRange(4,qu);
foreach(string s in al)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
2.4 刪除元素
ArrayList提供了三種方法將指定元素從集合中移除,這三種方法是Remove、RemoveAt和RemoveRange方法。
— Remove方法接受一個object類型值的參數,用於移除指定元素值的第一個匹配集合元素。
— RemoveAt方法接受一個int類型的參數,用於刪除指定索引的集合元素。
— RemoveRange方法從集合中移除一定範圍的元素。
這三個方法的聲明如下所示。
//從ArrayList實例中刪除與obj值匹配的第一個元素
public virtual void Remove(object obj);
//刪除指定索引位置index的元素
public virtual void RemoveAt(int index);
//從指定索引位置index開始,移除count個元素
public virtual void RemoveRange(int index, int count);
//下面示例演示了使用Remove方法。
static void Main(string[] args)
{
ArrayList al = new ArrayList(20);
al.AddRange(new string[8] { "元素一", "元素二", "元素三", "元素四", "元素五","元素六","元素七","元素八" });
//調用Remove方法刪除配置元素
al.Remove("元素二");
//調用RemoveAt方法刪除指定索引位置元素
al.RemoveAt(2);
//調用RemoveRange方法刪除指定範圍的元素
al.RemoveRange(3, 2);
foreach (string s in al)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
2.5 簡單排序
使用Sort方法,可以對集合中的元素進行排序。Sort有三種重載方法,聲明代碼如下所示。
//使用集合元素的比較方式進行排序
public virtual void Sort();
//使用自定義比較器進行排序
public virtual void Sort(IComparer comparer);
//使用自定義比較器進行指定範圍的排序
public virtual void Sort(int index, int count, IComparer comparer)
//本節只介紹如何使用第一種方法進行簡單的排序,下一節將介紹如何使用自定義的排序規則進行較複雜的排序。
//注意:爲使用Sort方法進行排序,集合中的所有元素必須實現IComparable接口,否則,將拋出異常。
//下面的示例演示瞭如何使用Sort方法進行排序。
static void Main(string[] args)
{
ArrayList al = new ArrayList();
al.AddRange(new string[8] { "Array1", "Array2", "Array3", "Array5", "Array4", "Array8", "Array7", "Array6" });
al.Sort();
foreach (string s in al)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
2.6 複雜排序
除了使用集合元素默認的比較器進行排序外,可以傳遞實現IComparer接口的類,按自定義的排序邏輯進行排序。上一節已經列出過Sort的三種重載方法,本節講述如何應用後兩種方法實現複雜排序。
舉一個場景:筆者有很多IT書籍,希望將書籍按着價格從高向低排序,或者將書籍按書名進行排序。下面的代碼演示了使用Sort類的重載方法進行復雜排序的方法。
//1.定義Book類
/// <summary>
/// 定義書籍類。具有三種屬性:書名,分類,價格
/// </summary>
public class Book
{
//定義書名屬性
private string _bookname;
public string BookName
{
get { return _bookname; }
set { _bookname = value; }
}
//定義書籍分類屬性
private string _bookcategory;
public string BookCategory
{
get { return _bookcategory; }
set { _bookcategory = value; }
}
//定義價格屬性
public double _price;
public double Price
{
get { return _price; }
set { _price = value; }
}
//書籍類的構造函數
public Book(string bookname,string bookcategory,double price)
{
_bookname = bookname;
_bookcategory = bookcategory;
_price = price;
}
}
//2.實現Icomparer接口的比較器
/// <summary>
/// 按價格從高到低排序
/// </summary>
public class InstanceCompare:IComparer
{
#region IComparer<Book> 成員
public int Compare(object x, object y)
{
//使用書籍類的價格進行比較
double i = ((Book)y).Price - ((Book)x).Price;
if (i > 0)
return 1;
else if (i < 0)
return -1;
else
return 0;
}
#endregion
}
/// <summary>
/// 按照書名從高到低排序
/// </summary>
public class BookNameCompare:IComparer
{
#region IComparer 成員
public int Compare(object x, object y)
{
//調用.NET預定義的按指定忽略大小寫的比較器比較書名
return new CaseInsensitiveComparer().Compare(((Book)y).BookName, ((Book)x).BookName);
}
#endregion
}
//3.調用Sort重載方法進行排序處理
static void Main(string[] args)
{
//聲明並初始化書籍數組
Book[] books = new Book[8]{new Book("C#書籍z","C#",45.5),new Book("C#書籍f","C#",55.8),
new Book("Delphi書籍1","Delphi",78),new Book("C#書籍x","C#",55.9),new Book("ASP.NET","ASP.NET",66),
new Book("Delphi書籍2","Delphi",79),new Book("C#書籍y","C#",60),new Book("C#書籍b","C#",80)};
ArrayList al = new ArrayList(books);
Console.WriteLine("排序前的集合排列");
DispalyResult(al);
//對數組按價格進行排序,調用InstanceCompare比較器
al.Sort(new InstanceCompare());
Console.WriteLine("按價格排序後的集合排列");
DispalyResult(al);
//對數組按書籍名稱進行排序,調用BookNameCompare比較器
al.Sort(new BookNameCompare());
Console.WriteLine("按書名排序後的集合排列");
DispalyResult(al);
Console.ReadLine();
}
4.//顯示數組內容
static void DispalyResult(ArrayList al)
{
foreach (Book book in al)
{
Console.WriteLine("書名:{0} 價格:{1}",book.BookName,book.Price);
}
}
2.7 查找元素
爲了在數組列表中查找元素,最常使用的是IndexOf或LastIndexOf方法,另外,還可以使用BinarySearch方法執行搜索。
— IndexOf方法從前向後搜索指定的字符串,如果找到,返回匹配的第一項的自0開始的索引,否則,返回-1。
— LastIndexOf方法從後向前搜索指定的字符串,如果找到,返回匹配的最後一項的自0開始的索引,否則,返回-1。
這兩個方法各自都有三個重載版本,表示從指定的索引處開始搜索或者是從指定索引處搜索指定長度的字符串。
BinarySearch使用二分算法從集合中搜索指定的值,並返回找到的從0開始的索引,否則,返回-1。下面的示例代碼將演示如何使用這些方法來查找數組中的元素。
static void Main(string[] args)
{
string[] str ={ "元素一", "元素二", "元素三", "元素四", "元素五", "元素六" };
ArrayList al = new ArrayList(str);
int i = al.IndexOf("元素三");
Console.WriteLine("元素三在集合中的位置是" + i);
i = al.LastIndexOf("元素五");
Console.WriteLine("元素五在集合中的位置是" + i);
int j = al.BinarySearch("元素三");
if (j >0)
Console.WriteLine("元素六在集合中的位置是" + j);
else
Console.WriteLine("沒有找到元素一");
Console.ReadLine();
}
2.8 遍歷列表
ArrayList內部維護着一個數組,可以通過下標進行訪問,而且ArrayList實現了IEnumerable接口,因此,要遍歷集合,可以使用for或foreach方法。
下面的代碼示例演示瞭如何使用for和foreach進行集合元素遍歷。
static void Main(string[] args)
{
ArrayList al = new ArrayList(new string[6] { "元素一", "元素二", "元素三", "元素四", "元素五", "元素六" });
//使用for遍歷
Console.WriteLine("for");
for (int i = 0; i <= al.Count - 1; i++)
{
Console.Write(al[i]);
}
Console.WriteLine("");
Console.WriteLine("foreach");
//使用foreach遍歷
foreach (object s in al)
{
Console.Write(s);
}
Console.ReadLine();
}