C#中的集合

来源:互联网 发布:网络平台注册协议 编辑:程序博客网 时间:2024/06/06 06:56

  大多数集合都在System.Collections,System.Collections.Generic两个命名空间。System.Collections.Generic是专门用于泛型集合。针对特定类型的集合类型位于System.Collections.Specialized;命名空间。线程安全的集合类位于System.Collections.Concurrent;命名空间。

      


一、下面列出非泛型和泛型集合的接口

非泛型集合接口          泛型集合接口              说明

ICollection            ICollection<T>           定义所有集合的大小(Count),枚举器(foreach)和同步(copyto)方法,继承自IEnumerable

IList               IList<T>               表示可按照索引单独访问的一组对象(像数组一样)

IDictionary             IDictionary<T>           表示键/值对的集合

IComparer              IComparer<T>            定义类型为比较两个对象而实现的方法

IEqualityComparer         IEqualityComparer<T>        定义方法以支持对象的相等比较

IEnumerable            IEnumerable<T>           公开枚举器。实现了该接口意味着允许foreach语句循环访问集合中的元素

IEnumerator            IEnumerator<T>           支持在泛型集合上进行简单迭代


基本上所有的接口都有泛型版本和非泛型版本。我这里主要讲的是泛型版本的集合,因为泛型集合是类型安全,没有装箱拆箱操

作,性能上相对要好于非泛型版本。并且在项目中以泛型版本为主。


Array,ArrayList,List<T>在我上一篇博客中有提及,这里不再重复。有需要的朋友可以看我的上一篇博文

Queue

public class Queue<T> : IEnumerable<T>, ICollection, IEnumerable

对象的先进先出集合。内部实现也是素组。

Stack

public class Stack<T> : IEnumerable<T>, ICollection, IEnumerable
后进先出 (LIFO) 集合。内部实现也是素组。

Hashtable、Dictionary、SortedList<TKey,TValue>、SortedDictionary<TKey,TValue>的比较

HashTable

public class Hashtable : IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback, ICloneable

HashTable是非泛型的,存储的key value都是object类型。
1.HashTable是一种散列表,他内部维护很多对Key-Value键值对,其还有一个类似索引的值叫做散列值(HashCode),它是根据GetHashCode方法对Key通过一定算法获取得到的,所有的查找操作定位操作都是基于散列值来实现找到对应的Key和Value值的。
2.我们需要使用一个算法让散列值对应HashTable的空间地址尽量不重复,这就是散列函数(GetHashCode)需要做的事。
3.当一个HashTable被占用一大半的时候我们通过计算散列值取得的地址值可能会重复指向同一地址,这就是哈希冲突。
在.Net中键值对在HashTable中的位置Position= (HashCode& 0x7FFFFFFF) % HashTable.Length,.net中是通过探测法解决哈希冲突的,当通过散列值取得的位置Postion以及被占用的时候,就会增加一个位移x值判断下一个位置Postion+x是否被占用,如果仍然被占用就继续往下位移x判断Position+2*x位置是否被占用,如果没有被占用则将值放入其中。当HashTable中的可用空间越来越小时,则获取得到可用空间的难度越来越大,消耗的时间就越多。
4.当前HashTable中的被占用空间达到一个百分比的时候就将该空间自动扩容,在.net中这个百分比是72%,也叫.net中HashTable的填充因子为0.72。例如有一个HashTable的空间大小是100,当它需要添加第73个值的时候将会扩容此HashTable.
5.这个自动扩容的大小是多少呢?答案是当前空间大小的两倍最接近的素数,例如当前HashTable所占空间为素数71,如果扩容,则扩容大小为素数131.


Dictionary<TKey,TValue>

public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, ISerializable, IDeserializationCallback

Dictionary是泛型的类,类型安全的
1.Dictionary是一种变种的HashTable,它采用一种分离链接散列表的数据结构来解决哈希冲突的问题。
2.分离链接散列表是当散列到同一个地址的值存为一个链表中。
3.这个变种HashTable的填充因子是1


HashTable和Dictionary的区别

1.HashTable不支持泛型,而Dictionary支持泛型。HashTable 的元素属于 Object 类型,对值类型进行操作需要装箱拆箱,比较耗时。

2.单线程程序中推荐使用 Dictionary, 有泛型优势, 且读取速度较快, 容量利用更充分。多线程程序中推荐使用 Hashtable, 默认的 Hashtable 允许单线程写入, 多线程读取, 对 Hashtable 进一步调用 Synchronized() 方法可以获得完全线程安全的类型. 而 Dictionary 非线程安全, 必须人为使用 lock 语句进行保护, 效率大减。


SortedList<TKey,TValue>

public class SortedList<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable


SortedDictionary<TKey,TValue>

public class SortedDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable


SortedList<TKey,TValue>SortedDictionary<TKey,TValue>都实现了IDictionary<TKey, TValue>接口,都对key进行了排序。SortedList 泛型类是具有 O(logn) 检索的二进制搜索树,其中 n 是字典中元素的数目。就这一点而言,它与SortedDictionary<TKey,TValue>泛型类相似。这两个类具有相似的对象模型,并且都具有 O(log n) 的检索运算复杂度。

SortedList<TKey,TValue>SortedDictionary<TKey,TValue>的区别:

这两个类的区别在于内存的使用以及插入和移除元素的速度:

      1.SortedList 使用的内存比 SortedDictionary 少。

      2.SortedDictionary 可对未排序的数据执行更快的插入和移除操作,它的运算复杂度为 O(logn),而 SortedList 的运算复杂度为 O(n)。

      3.如果使用排序数据一次性填充列表,则 SortedList 比 SortedDictionary 快。


HashSet<T>与SortedSet<T>

HashSet<T>

public class HashSet<T> : ISerializable, IDeserializationCallback, ISet<T>, ICollection<T>, IEnumerable<T>, IEnumerable

SortedSet<T>

public class SortedSet<T> : ISet<T>, ICollection<T>, IEnumerable<T>, ICollection, IEnumerable, ISerializable, IDeserializationCallback

他们都实现了 System.Collections.Generic.ISet 接口.HashSet和SortSet主要的作用是用来进行两个集合求交集、并集、差集等运算.集合中包含一组不重复出现且无特性顺序的元素。前者不会自动排序,后者会加入元素后,自动排序。两者都无法从特定位置访问其中某个元素。a


线程安全的集合,都是以Concurrent命名开头,所谓线程安全,当多个线程访问同一个集合时,一次只能由一个线程访问,不会引起一个线程在读,一个线程在写等同时进行的操作。

  • ConcurrentBag<T>是线程安全的List<T>

    public class ConcurrentBag<T> : IProducerConsumerCollection<T>, IEnumerable<T>, ICollection, IEnumerable

    ConcurrentDictionary<TKey,TValue> 是线程安全的Dictionary<TKey,TValue>

    public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable

    ConcurrentQueue<T> 是线程安全的Queue<T>

    ConcurrentStack<T>是线程安全的Stack<T>

  • 0 0
    原创粉丝点击