认识.NET的集合

集合(collection)提供了一种结构化组织任意对象的方式,而且我们早就知道集合在日常编程工作中的重要性。.NET类库提供了丰富的集合数据类型,其种类之繁多甚至使许多人看得眼都花了,这些集合对象都具有各自的专用场合。不管怎么说,更多的选择也就意味着更高的灵活性,但同时也意味着更高的复杂性。因此,对集合各个类型的用途和使用条件具有适度的了解是完全必要的。下面就请随我进行一场.NET集合之旅吧!
.NET集合定义

从.NET的角度看,所谓的集合可以定义为一种对象,这种对象实现一个或者多个System.Collections.ICollectionSystem.Collections.IDictionarySystem.Collections.IList接口。这一定义把System.Collections名称空间中的“内置”集合划分成了三种类别:

  • 有序集合:仅仅实现ICollection接口的集合,在通常情况下,其数据项目的插入顺序控制着从集合中取出对象的的顺序。System.Collections.Stack和 System.Collections.Queue类都是ICollection集合的典型例子。
  • 索引集合:实现Ilist的集合,其内容能经由从零开始的数字检索取出,就象数组一样。System.Collections.ArrayList对象是索引集合的一个例子。
  • 键式集合:实现 IDictionary 接口的集合,其中包含了能被某些类型的键值检索的项目。IDictionary集合的内容通常按键值方式存储,可以用枚举的方式排序检索。 System.Collections.HashTable类实现了IDictionary 接口。

正如你看到的那样,给定集合的功能在很大程度上受到特定接口或其实现接口的控制。如果你对面向对象编程缺乏了解,那么你可能对上面说的这些话感到难以理解。不过你至少应该知道,以接口这种方式构造对象的功能不但造就了具有整套类似方法的对象族,而且还能让这些对象在必要的情况下可以当作同类,以OOP(面向对象编程)的术语来说,这就是大名鼎鼎的多态性技术。

System.Collections概述

System.Collections名称空间包含了在你的应用程序中可以用到的6种内建通用集合。另一些更为专业化的集合则归属于System.Collections.Specialized,在某些情况下你会发现这些专用集合也是非常有用的。加上一些异常(exception)类,这些专业化集合在功能上和内建集合是类似的。现在就让我们审视一下通用集合以及少量的不太富于专业化的集合。

堆栈和队列

System.Collections.Stack 和 System.Collections.Queue 类,两者仅仅实现了ICollection 接口,按照存储项目加到集合的顺序保存System.Object类型的项目。对象只能按其加入顺序从集合中检索:堆栈是后进先出,而队列则是先进先出。通常情况下,你在以下场合可以考虑采用以上这些集合:

  • 接收和处理集合内项目时顺序比较重要。
  • 你能在处理项目之后丢弃它。
  • 你不需要访问集合中的任意项目。

ArrayList

System.Collections.ArrayList类,仅仅实现 Ilist,最适合描述为一种正常数组和集合的混合类型。ArrayList按照项目被加入集合的顺序存储项目。每个项目都被分配一个索引标识符而且能由关联它们的索引数字以任何顺序被检索。当新项目加入集合时会扩大ArrayList从而令其相比普通数组更具灵活性。然而,ArrayList负载比传统数组更大而且没有实现严格的类型化,也就可以接受任何转换为System.Object的对象(换句话说,对什么东西都来者不拒)。

SortedList

System.Collections.SortedList,它实现了IDictionary和ICollection接口,是最基本的排序集合,与Vb6下的Collection对象非常类似。SortedList存储对象并按照关联的键值对这些存储对象排序。它们也是同时支持索引数字和键对象检索的唯一内建的.NET集合。

HashTable

强有力的System.Collections.HashTable集合实现了IDictionary 和 Icollection,能用来存储多种类型的对象连同关联的唯一字符串键值。在HashTable集合中的项目按照源自其键值的哈希代码所确定的顺序存储。集合内每个对象的键值都必须唯一,而其哈希代码则不一定唯一。


什么是哈希代码?
哈希代码实质上就是从一快数据中消除所有冗余部分之后的结果,它主要起到对数据辅助分类或排序的作用。

当某个项目加入集合时,HashTable即调用键值的GetHashCode方法,由于所有的类都是从System.Objec继承的,所以调用该方法即可确定该类的哈希代码并且按该代码排序存储。你可以强迫使用定制的哈希函数,方法有二,一是重载类的GetHashCode方法,二是向HashTable构造器传递实现了System.Collections.IHashcodeProvider接口的对象,在这种情况下,该对象将用于为所有加入集合的键值产生哈希代码。

从性能的角度看,因为键值搜索仅限于具有同样哈希代码的键值,所以HashTable能够很快地从集合中检索任意一个元素,从而减少了必须通过检查以发现匹配的键值的数量。然而,因为插入到集合中的每个对象-键值对都必须产生相应的哈希代码,所以项目插入的代价就有点高了。因此,HashTable主要运用在按照任意键值反复检索大量相对静态的数据这一场合下。

ListDictionary 和 HybridDictionary

ListDictionary 和 HybridDictionary 类归属于System.Collections.Specialized。它们都在按照唯一键值的原则来组织项目,而且都实现了 IDictionary 和 ICollection 。ListDictionary在内部以链表的方式存储项目,建议用在不会增长超过10个项目的集合中。HybridDictionary采用一个内部链表(实际上就是ListDictionary)作为小集合,当集合变得足够大(超过10个项目)以至于链表实现效率降低时就会转换为HashTable。

StringCollection 和 StringDictionary

System.Collections.Specialized.StringCollection 和 System.Collections.Specialized.StringDictionary 都对存储字符串的集合进行了优化。 StringCollection实现了 IList 和 ICollection 而且实质上就是ArrayList,只不过实现了强烈的类型化仅仅接受字符串而已。StringCollection最理想的应用场合是经常更新或增加的少量数据,而StringDictionary则最适用于不经常增加项目到诸如HashTable之类集合中的大量数据。

NameValueCollection

System.Collections.Specialized.NameValueCollection最有趣的地方在于它能包含关联同一键值的多个项目,这正是它与其他内建集合的差别所在。除此以外,它在功能上类似HashTable,按照源自每一项目键值的哈希代码对项目排序从而也具有类同的优缺点。

存在的问题

如果说由 .NET 类库所提供的内建集合也存在问题的话,那多半是它们几乎都在内部把项目存储为System.Object.类型。从最大灵活性的角度看那是一个好想法,但同时也给采用这些通用集合的程序员提出了一些问题。首先,只要你把一个新项目加到集合中去,运行时就必须实施类型转换操作(创建值类型的索引以便可以当作对象引用)。这是一种低效的操作而且在处理大型集合时会产生相当可观的性能问题。其次,只要你访问通用集合中的一个项目,该项目都将作为System.Object类型被返回,这就意味着你不得不把它转换为真实的类型才能对其进行有意义的操作。

posted @ 2008-05-06 17:34  彷徨......  阅读(977)  评论(1编辑  收藏  举报