C# 2012程序设计实践教程 (清华电脑学堂)
上QQ阅读APP看书,第一时间看更新

5.3 集合类

集合是与数组最为相似的数据类型,它弥补了数组长度不能够增加、插入和删除都不宜操作的特点,使用动态的数据成员和长度,可快捷地执行其成员的插入和删除。

C#内置了多种集合类,不同的集合类适用于不同的地方,如一些集合可以被当作是动态数组来使用,这些长度可变的数据集能够在程序执行中改变数组的长度,可以增加、释放数组元素所占的空间。除此之外,C#还提供了对堆栈、队列、列表和哈希表等的支持。

5.3.1 集合类概述

集合类是定义在System.Collections或System.Collections.Generic命名空间的一部分,因此需要在使用之前添加以下语句。

    using System.Collections.Generic;
    using System.Collections;

在C#中,所有集合都实现了ICollection接口,而ICollection接口继承自IEnumerable接口,所以每个内置的集合也都实现了IEnumerable接口。

接口的继承需要将接口中的方法全部实现,因此集合类中都含有ICollection接口成员,这些成员是集合类分别拥有实现、功能相似的。ICollection接口的成员及其作用说明如表5-3所示。

表5-3 ICollection接口的成员

接口成员表明集合对象都可以有表5-3中的成员。这些成员在各自的类中实现,功能一样,可以直接使用。

集合和数组都是数据集,用来处理一系列相关的数据,包括集合元素和数组元素的初始化、赋值、遍历等,但有以下几点不同。

(1)数组是长度固定,不能伸缩的。

(2)数组要声明元素的类型,集合类的元素类型却是Object。

(3)数组可读可写,不能声明只读数组。集合类可以提供ReadOnly()方法以只读方式使用集合。

(4)数组要有整数下标才能访问特定的元素,但集合可以通过其他方式访问元素,而且不是每个集合都能够使用下标。

集合类大多分布在System.Collections命名空间下,常见的集合类及其说明如表5-4所示。

表5-4 System.Collections命名空间常用的集合类

不同的类针对不同的数据对象,有些类是可以完成相同功能的,但类的侧重不同,运行效率就不同。

5.3.2 ArrayList类

ArrayList类的集合又称作动态数组或可变数组,数组可以看作是数据的集合,而动态数组是数据的动态集合。

动态数组与静态数组的声明和定义完全不同,静态数组可以直接由数据类型定义,而动态数组需要根据不同的类来实例化。

ArrayList类位于System.Collections命名空间中,所以在使用时,需要导入此命名空间,具体做法是在程序文档最上方添加下面的语句。

    using System.Collections;

命名空间导入之后就可以创建使用ArrayList类的对象了。由于动态数组可以改变数组长度,因此在声明时不需要指定其数组长度,如创建动态数组list,语法如下所示:

    ArrayList list = new ArrayList();

ArrayList类的属性和方法及其应用如表5-5和表5-6所示。

表5-5 ArrayList类的属性

表5-6 ArrayList类的方法

在表5-6中有对数据元素的多种删除方法,而表5-2中只有对数据元素的清除方法。静态数组的长度是不能改变的,长度的改变将导致数组被重新定义,因此没有提供静态数据删除元素的方法。上述方法都是可以直接使用的,如向动态数组中添加元素有Add()方法和Insert()方法。

【范例7】

定义ArrayList类数组list,分别使用Add()方法和Insert()方法添加数组元素,并输出所有元素值,及数组元素的个数,代码如下。

    ArrayList list = new ArrayList();
    list.Add(1);
    list.Add(2);
    list.Add(3);
    list.Add(4);
    list.Insert(3,0);
    foreach (object listnum in list)
    {
        Console.Write("{0} ",listnum);
    }
    Console.WriteLine(""); 
    Console.WriteLine(list.Count);

执行结果为:

    1 2 3 0 4
    5

由于ArrayList类型数组的元素是object类型,因此无法通过索引的方式来访问具体成员。对于ArrayList类型数组的遍历,无法使用for循环语句来执行。

5.3.3 Stack集合类

Stack集合又称作堆栈,堆栈中的数据遵循后进先出的原则,即后来被添加的元素将默认首先被遍历。如依次将1、2、3这三个元素加入堆栈,则使用foreach in语句遍历输出时,输出结果为:321。

Stack集合的容量表示Stack集合可以保存的元素数。默认初始容量为10。向Stack添加元素时,将通过重新分配来根据需要自动增大容量。Stack集合具有以下属性。

(1)Count:获取Stack中包含的元素数。

(2)IsSynchronized:获取一个值,该值指示是否同步对Stack的访问。

(3)SyncRoot:获取可用于同步Stack访问的对象。

如果元素数Count小于堆栈的容量,则直接将对象插入集合的顶部,否则需要增加容量以接纳新元素,将元素插入集合尾部。Stack集合接受null作为有效值,并且允许有重复的元素。

Stack集合类有公共方法和受保护的方法,供继承和使用。其中,常用的公共方法如表5-7所示。

表5-7 Stack集合类常用方法

5.3.4 Queue集合类

Queue集合又称作队列,是一种表示对象的先进先出集合。队列按照接收顺序存储,对于顺序存储、处理信息比较方便。Queue集合可看作是循环数组,元素在队列的一端插入,从另一端移除。

Queue的默认初始容量为32,元素添加时,将自动重新分配,增大容量。还可以通过调用TrimToSize来减少容量。

集合容量扩大时,扩大一个固定的倍数,这个倍数称作等比因子,等比因子在Queue集合类创建对象时确定,默认为2。Queue集合同样接受null作为有效值,并且允许重复的元素。

Queue集合类的属性都是共有的,可以直接使用,共有以下三个。

(1)Count:获取Queue中包含的元素数。

(2)IsSynchronized:是否同步对Queue的访问。

(3)SyncRoot:可用于同步Queue访问的对象。

Queue集合类有着公共方法和受保护的方法,同样有着与ArrayList类和Stack类作用相似的方法,如表5-8所示。

表5-8 Queue集合类常用方法

5.3.5 BitArray集合类

BitArray集合类专用于处理bit类型的数据集合,集合中只有两种数值:true和false。可以用1表示true,用0表示false。

BitArray集合元素的编号(索引)同样是从0开始,与前几个集合不同的是,BitArray集合类在创建对象时,需要指定集合的长度,如定义长度为3的bitnum对象,使用代码如下所示:

    BitArray bitnum = new BitArray(3);

若编写索引时超过BitArray的结尾,将引发异常。但BitArray集合类的长度属性Length不是只读的,可以在添加元素时重新设置。BitArray集合类的属性和方法如表5-9和表5-10所示。

表5-9 BitArray集合类公共属性

表5-10 BitArray集合类常用方法

5.3.6 SortedList集合类

SortedList集合类又称作排序列表类,是键/值对的集合。SortedList集合的元素是一组键/值对,这种有着键和值的集合又称作字典集合,在C#中有SortedList集合和Hashtable集合这两种字典集合。

SortedList的默认初始容量为0,元素的添加使集合重新分配、自动增加容量。容量可以通过调用TrimToSize()方法或设置Capacity属性减少容量。

在SortedList集合内部维护两个数组以存储列表中的元素:一个数组用于键,另一个数组用于相关联的值。SortedList集合元素具有以下特点。

(1)SortedList集合中的键不能为空null,但值可以。

(2)集合中不允许有重复的键。

(3)键和值可以是任意类型的数据。

(4)每个元素都可作为DictionaryEntry对象的键/值对。

(5)SortedList集合中的元素的键和值可以分别通过索引访问。

(6)索引从0开始。

(7)使用foreach in语句遍历集合元素时需要集合中的元素类型,SortedList元素的类型为DictionaryEntry类型。

(8)集合中元素的插入是顺序插入,操作相对较慢。

(9)SortedList允许通过相关联键或通过索引对值进行访问,提供了更大的灵活性。

(10)键值可以不连续,但键值根据索引顺序排列。

SortedList集合索引的顺序是基于排序顺序的,集合中元素的插入类似于一维数组的插入排序法:每添加一组元素,都将元素按照排序方式插入,同时索引会相应地进行调整。

当移除元素时,索引也会相应地进行调整。因此,当在SortedList中添加或移除元素时,特定键/值对的索引可能会被更改。SortedList集合类的常用属性和方法,及其说明如表5-11和表5-12所示。

表5-11 SortedList集合类常用属性

表5-12 SortedList集合类常用方法

SortedList集合中以任意顺序添加的元素,已经按照键值从小到大排列了。SortedList集合元素顺序排列是根据键的值,而不是元素值的值。元素的值可以通过索引替换,也可以分别通过键和索引移除元素。

5.3.7 Hashtable集合类

Hashtable集合类是一种字典集合,有键/值对的集合。同时,Hashtable集合又被称作哈希表。

哈希表是根据关键码值而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。Hashtable类在内部维护着一个内部哈希表,这个内部哈希表为高速检索数据提供了较好的性能。内部哈希表为插入到Hashtable的每个键进行哈希编码,在后续的检索操作中,通过哈希代码,可以遍历所有元素。

由于Hashtable集合有键和值,属于字典集合,因此有着与SortedList集合相同的以下几个特点。

(1)每个元素都可作为DictionaryEntry对象的键/值对被访问。

(2)Hashtable集合中的键不能为空null,但值可以。

(3)使用foreach in语句遍历集合元素时需要集合中的元素类型,Hashtable元素的类型为DictionaryEntry类型。

(4)键和值可以是任意类型的数据。

Hashtable的默认初始容量为0。随着向Hashtable中添加元素,容量通过重新分配按需自动增加。当把某个元素添加到Hashtable时,将根据键的哈希代码将该元素放入存储桶中。该键的后续查找将使用键的哈希代码只在一个特定存储桶中搜索。

在哈希表中,键被转换为哈希代码,而值存储在存储桶中。Hashtable集合没有自动排序的功能,也没有使用索引的方法,它需要将键作为索引使用。Hashtable集合类提供了15个构造函数,常用的有如下4个,如表5-13所示。

表5-13 Hashtable类构造函数

关于Hashtable集合的属性和方法如表5-14和表5-15所示。

表5-14 Hashtable类常用属性

表5-15 Hashtable类常用方法