集 合
List和ArrayList是与数组相当的集合类。还有其他类型的集合:队列、栈、链表和字典。
集合接口和类型
集合类可以组合为集合,存储Object类型的元素和泛型集合类。在CLR 2.0之前,不存在泛型。现在泛型集合类通常是集合的首选类型。泛型集合类是类型安全的,如果使用值类型,是不需要装箱操作的。如果要在集合中添加不同类型的对象,且这些对象不是相互派生的,例如在集合中添加int和string对象,就只需基于对象的集合类。另一组集合类是专用于特定类型的集合,例如StringCollection类专用于string类型。
对象类型的集合位于System.Collections命名空间;泛型集合类位于System.Collections. Generic命名空间;专用于特定类型的集合类位于System.Collections.Specialized命名空间。
队列
队列是其元素以先进先出(FIFO)的方式来处理的集合。先放在队列中的元素会先读取。队列的例子有在机场排的队、人力资源部中等待处理求职信的队列、打印队列中等待处理的打印任务、以循环方式等待CPU处理的线程。另外,还常常有元素根据其优先级来处理的队列。
栈
栈是与队列非常类似的另一个容器,只是要使用不同的方法访问栈。最后添加到栈中的元素会最先读取。栈是一个后进先出(LIFO)容器。
链表
LinkedList集合类没有非泛型集合的类似版本。LinkedList是一个双向链表,其元素指向它前面和后面的元素
链表的优点是,如果将元素插入列表的中间位置,使用链表会非常快。在插入一个元素时,只需修改上一个元素的Next引用和下一个元素的Previous引用,使它们引用所插入的元素。在List和ArrayList类中,插入一个元素,需要移动该元素后面的所有元素。
当然,链表也有缺点。链表的元素只能一个接一个地访问,这需要较长的时间来查找位于链表中间或尾部的元素。
链表不仅能在列表中存储元素,还可以给每个元素存储下一个元素和上一个元素的信息。这就是LinkedList包含LinkedListNode类型的元素的原因。
有序表
如果需要排好序的表,可以使用SortedList<TKey, TValue>。这个类按照键给元素排序。
下面的例子创建了一个有序表,其中键和值都是string类型。默认的构造函数创建了一个空表,再用Add()方法添加两本书。使用重载的构造函数,可以定义有序表的容量,传送执行了IComparer<TKey>接口的对象,用于给有序表中的元素排序。
Add()方法的第一个参数是键(书名),第二个参数是值(ISBN号)。除了使用Add()方法之外,还可以使用索引器将元素添加到有序表中。索引器需要把键作为索引参数。如果键已存在,那么Add()方法就抛出一个ArgumentExeption类型的异常。如果索引器使用相同的键,就用新值替代旧值。
字典
字典表示一种非常复杂的数据结构,这种数据结构允许按照某个键来访问元素。字典也称为映射或散列表。字典的主要特性是能根据键快速查找值。也可以自由添加和删除元素,这有点像List<T>,但没有在内存中移动后续元素的性能开销。
用作字典中键的类型必须重写Object类的GetHashCode()方法。只要字典类需要确定元素的位置,就要调用GetHashCode()方法。GetHashCode()方法返回的int由字典用于计算放置元素的索引。这里不介绍这个算法。我们只需知道,它涉及到素数,所以字典的容量是一个素数。
GetHashCode()方法的实现代码必须满足如下要求:
● 相同的对象应总是返回相同的值。
● 不同的对象可以返回相同的值。
● 应执行得比较快,计算的开销不大。
● 不能抛出异常。
● 应至少使用一个实例字段。
● 散列码值应平均分布在int可以存储的整个数字区域上。
● 散列码最好在对象的生存期中不发生变化。
提示:
字典的性能取决于GetHashCode()方法的实现代码。
Lookup类
Dictionary<TKey, TValue>只为每个键支持一个值。新类Lookup<TKey, TElement>是.NET 3.5中新增的,它类似于Dictionary<TKey, TValue>,但把键映射到一个值集上。这个类在程序集System.Core中实现,用System.Linq命名空间定义。
HashSet
.NET 3.5在System.Collections.Generic命名空间中包含一个新的集合类:HashSet<T>。这个集合类包含不重复项的无序列表。这种集合称为"集(set)"。集是一个保留字,所以该类有另一个名称HashSet<T>。这个名称很容易理解,因为这个集合基于散列值,插入元素的操作非常快,不需要像List<T>类那样重排集合。
位数组
BitVector32