常用类库--集合

集合

在C#中集合类被定义在Collection(非泛型)、Collection.Generic(泛型)命名空间下。专用于特定类型的集合类位于System.Collections.Specialized名称空间中。线程安全的集合类位于System.Collections.Concurrent名称空间中。

要全面的掌握集合,必须首先要理解一些数据结构的知识。所谓数据结构,就是相互之间存在一种或多种特定关系的数据元素的集合。结合下图,看一下对集合的分类。

集合总体上分为线性集合和非线性集合

线性集合指元素具有唯一的前驱和后驱的数据结构类型。

线性集合按存储方式,又分为直接存储和顺序存储。

直接存储是指:该类型的集合数据元素可以直接通过下标(也即index)来访问,在C#中有三种形式:Array(包括数组和List<T>),string,struct。

直接存储结构的优点是:向数据结构中添加元素是很高效的,只要直接放在数据末尾的第一个空位上就可以了。它的缺点是:向集合插入元素将会变得低效,它需要给插入的元素腾出位置并顺序移动后面的元素。

List<T>操作:string和structs虽然是直接存储结构,但它们与一般的集合定义有很大的不同。在直接存储的数据结构中,需要区分的是数组和List<T>的选择。再次强调一下:如果集合的数目固定并且不涉及到转型,使用数组效率高,否则就使用List<T>。

顺序存储结构,也即线性表。线性表的大小可动态的扩大和缩小,它在一片连续的区域中存储数据元素。线性表不能按照索引进行查找,它通过对地址的引用来搜索元素,为了找到某个元素,它必须遍历所有元素,直到找到对应的元素为止。所以线性表的优点是插入和删除数据效率高,而缺点是查找的效率相对来说低一些。

线性表又可以分为队列、栈以及索引群集,在C#中,分别表现为: Queue<T>,Stack<T>,索引群集又进一步泛化为字典类型Dictionary< TKey, TValue >和双向链表LinkedList<T>。

队列操作:队列Queue<T>遵循的是先入先出模式,它在集合末尾添加元素,在集合起始删除元素,如图:

根据队列的特点,可以用来处理并发命令等场景:将所有客户端的命令先入队,由专门的工作线程来执行队列的命令。在分布式中的消息队列就是一个典型的队列应用实例。

栈操作:栈Stack<T>遵循的是后入先出模式,它在集合末尾添加元素,同时也在集合末尾删除元素,如图:

字典Dictionary< TKey, TValue >操作:字典Dictionary<TKey, TValue>存储的是键值对,值在基于键的散列码的基础上进行存储。字典类对象由包含集合元素的存储桶组成,每一存储桶与基于该元素的键的哈希值关联。如果需要根据键进行值的查找,使用Dictionary<TKey, TValue>将会使搜索和检索更会快捷。

链表LinkedList<T>操作:双向链表LinkedList<T>是一个类型为LinkedListNode的元素对象的集合。当在集合中觉得插入和删除数据很慢的时候,可以考虑使用链表。如果使用LinkedList<T>,会发现此类型并没有其它集合普遍具有的Add方法,取而代之的是AddAfter、AddBefore、AddFirst、AddLast等方法。双向链表中的每个节点都向前指向Previous节点,向后指向Next节点。

非线性集合是指具有多个前驱或后驱的数据结构类型,如:树、图。

在FCL(FrameWork类库)中,非线性集合实现的不多。非线性集合分为层次集合和组集合。层次集合,如树,在FCL中就没有实现。组集合,又分为集和图。集在FCL中实现为HashSet<T>,而图在FCL中也没有对应实现。集的概念在本意上是指存放在集合中的元素是无序的且不能重复的。下图演示了集的用途:

其他集合:

除了上面我们提到的集合类型,还有其他几个要掌握的集合类型,它们是在实际应用中发展出来的对以上基础类型的扩展:SortedList<T>,SortedDictionary<TKey, TValue>,SortedSet<T>。它们所扩展的对应类为List<T>,Dictionary<TKey,TValue>,HashSet<T>,作用是将原本无序排列的元素,变为有序排列。

除了排序上的需求增加了上面3个集合类,在命名空间System.Collections.Concurrent下,还涉及几个多线程集合类。它们主要是:ConcurrentBag<T>对应List<T>,ConcurrentDictionary<TKey, TValue>对应Dictionary<TKey, TValue>,ConcurrentQueue<T>对应Queue<T>,ConcurrentStack<T>对应Stack<T>。如果集合被用于多线程应用中,可以使用这几个集合类型。

下面给出一个主要集合类的类图。实际工作中,应该根据需要选择合适的集合类。

 

ArrayList 、List<T>

属性:

1.count属性:用来获取集合中实际包含的元素个数。

2.capacity属性:指集合容量,即集合包含的元素数,可理解为capacity>=count;当向集合中添加的元素个数超过了capacity时,容量就会翻倍。

方法:

1.Sort():对集合按默认排序方式进行排序,内部调用CompareTo方法。

注:集合中元素能够排序的条件是实现ICompareable接口。

Sort(Icomparer comparer)方法,通过Icomparer比较器接口来实现排序。

List<T>集合的用法与ArrayList集合基本相同,建议在使用List<T>

Hashtable、Dictionary<K,V>

Hashtable集合中的“键”不能重复,必须唯一。

Dictionary<K,V>集合的用法与Hashtable集合基本相同,建议在使用Dictionary<K,V>

posted @ 2014-08-23 21:07  百年一人  阅读(435)  评论(0编辑  收藏  举报