集合是一些有奇特特征的自力数据项形成的,经过集合,我们可以可运用沟通的调用代码来搞定一个集合的整个元素,而不必单独搞定每一个单独的项。.net的集合诸如(System.Array类以及 System.Collections定名空间)数组、列表、行列、仓库、哈希表、字典乃至(System.Data下)DataSet、DataTable,另有2.0中加入的集合的泛型版本(System.Collections.Generic和 System.Collections.ObjectModel),4.0中引入的有用线程平静把持的集合(System.Collections.Concurrent)。
面临于这么多的集合,你领会各个集合有哪些优势,正在一个特定的场景中运用哪一个集合吗?本文试图商讨一下这个标题,寻常而谈,不涉及深入的内存数据规划的追究,但愿能给各人带来一些益处。
集合接口 正在离开接头各类集合以前,我们先接头一下集合的特性,整个集合体系的承袭条理。
ICollection 接口是 System.Collections 定名空间中类的基接口,而响应的ICollection<T>是整个泛型版本集合的基接口。整个的的集合类都间接或许间接的承袭他们。
ICollection又承袭IEnumerable,来提供方便的罗列功能,可是更值得注意ICollection提供同步访问的线程平静性控制:
IsSynchronized:取得一个值,该值指示是否同步关于 ICollection 的访问(线程平静)。
SyncRoot:取得可用于同步关于 ICollection 的访问的关于象。
比喻,我们可以经过如下来关于集合举办线程平静访问,可是有些集合提供Synchronized方法来提供线程平静集合的封装。复制代码 代码以下:ICollection myCollection = someCollection;lock(myCollection.SyncRoot){ // Insert your code here.} 可是默认环境下集合不是线程平静的。如果必要关于集合举办可伸缩的且高效的多线程访问,请运用System.Collections.Concurrent定名空间中的某个类。
而与非泛型版本区别的是,泛型版本的集合除了了实现了泛型的接口外,也实现了非泛型的响应的接口。如ICollection<T>实现了IEnumerable和IEnumerable<T>,可是泛型集合却没有提供同步访问的线程平静控制,也便是说泛型集合的同步访问,我们必须自己去搞定同步或许运用System.Collections.Concurrent定名空间中的某个类。
别的,IList和IDictionary离开承袭自ICollection,IList的实现者(如Array、ArrayList 或许 List<T>等)和ICollection的实现者(比喻 Queue、ConcurrentQueue<T>、Stack、 ConcurrentStack<T>或许 LinkedList<T>)的每逐个个元素都是一个值,而IDictionary的实现者(比喻 Hashtable 和 SortedList 类、Dictionary<TKey, TValue> 和 SortedList<TKey, TValue> 泛型类)每逐个个元素都是一个键值关于。
接上去,我们将离开接头和有点下一些常常的集合。
数组Array Array不是System.Collections的一部份,可是它承袭自IList接口。.net的Array可以有多维数组、交错数组,乃至创建下限不是0是数组,默认环境下保举运用下限是0的一维数组,这常常的数组是颠末优化的,机能最高。
与System.Collections集合区别的是,Array具有稳固的容量,若要增加容量,您必须创建具有所需容量的新 Array 关于象,将旧 Array 关于象中的元素复制到新关于象中,然后删除了该旧 Array。而System.Collections下的集合正在抵达以后容量时可自动扩张容量:内存被从头分派,元素从旧集合复制到新集合中。 这淘汰了运用集合所需的代码,可是,集合的机能大约仍受到失望影响。 是以我们应将初始容量配置为集合的估计的巨细以避免因多次从头分派导致的欠安机能。
System.Collections下的集合类 该典范的集合都具有排序功能且大大都颠末了索引。能自动搞定内存操持,容量按需扩张。
ArrayList和List<T>:List<T>是ArrayList的泛型版本,它们和Array同样都是基于索引访问,每逐个个数据项只保存一个数据值,可是它们提供比Array更强大的功能和把持,使得它们也更易运用。机能方面,泛型版本老是比非泛型更优先采用,除了非成员典范是object典范,因为泛型版本免除了装箱和拆箱的把持;正在不必要从头分派集合容量的环境下,List<T>的机能与同典范的数组十分临近。别的,ArrayList可以很方便的创建同步版本,但Array和List<T>的同步义务必须有自己实现。
Hashtable 和 Dictionary 集合典范:这些集合每逐个个项是一个键值关于。Dictionary<Tkey,Tvalue>是Hashtable的泛型版本。Hashtable关于象是由包含集合元素的存储桶形成的,每逐个个存储桶与运用元素键基于哈希函数天生的一个哈希码联络关系,包含多个元素。是以这种集合比别的的大大都集合正在搜索和检索数据上更疾速。而一样的Dictionary<Tkey,Tvalue>老是比Hashtable机能更好,是以保举运用,多线程同步运用ConcurrentDictionary<TKey, TValue>类。
已经排序的集合典范:System.Collections.SortedList 类、System.Collections.Generic.SortedList<TKey, TValue> 泛型类和System.Collections.Generic.SortedDictionary<TKey, TValue> 泛型类,它们都实现 IDictionary 接口,两个泛型类还实现了System.Collections.Generic.IDictionary<TKey, TValue>,与Hashtable相同每逐个个元素都是一个键值关于,可是它们以基于键的排序顺序掩护元素,并无哈希表的 O(1) 插入和检索特性。非泛型的罗列项是DictionaryEntry 关于象,而两个泛型典范返回 KeyValuePair<TKey, TValue> 关于象。它们最缓和的重点是它们是依据System.Collections.IComparer实现或许System.Collections.Generic.IComparer<T>的实现排好序的。SortedList允许我们经过索引和键访问,而SortedDictionary只能经过键访问,SortedList还更省内存。
行列和仓库:就未多少做先容了,如果要权且存储数据,数据只正在访问一次后就维持,便可以运用这种集合。行列和仓库的不同就正在于访问的前后纷歧样,信任各人都很清楚了。他们也离开有各自的泛型版本和线程平静版本:System.Collections.Queue 类、System.Collections.Generic.Queue<T> 类和System.Collections.Concurrent.ConcurrentQueue<T>,System.Collections.Stack类以及 System.Collections.Generic.Stack<T> 和System.Collections.Concurrent.ConcurrentStack<T>。
Set集合:该典范集合的两个典范HashSet<T> 和 SortedSet<T>,都实现了ISet<T>接口。Set集合最濒临于数学中的集合,特别用于实现了数学的Set把持,如并集、交集等运算。此中Hashset<T>没有排序,不克不及有重复元素,可以视为Dictionary<TKey,TValue>的不包含值的版本,基于哈希键提供高机能的Set运算。而SortedSet<T>提供排好序的Set把持的集合。此处要提的是有些集合也提供了Set运算的扩张方法和LINQ也提供的Set运算,可是它们都返回新 的IEnumerable<T>集合,而Set集合的Set把持都是修改以后集合,而且提供一个更大、更靠得住的运算集合。
这其实不是.net集合的全数,它另有位集合和公用集合。
位集合 它的每逐个个元素是一个标识位,而不是关于象。此中有BitVector32和BitArray。
BitVector32是一个规划,只能存储32位数据,可用来存储位标识或许小整数,它是值典范,是以机能更好。
而BitArray是援用典范,它的容量始终与计数沟通,可以经过Length属性来分派或许删除了元素。
公用集合 NameValueCollection 基于 NameObjectCollectionBase;但NameValueCollection 蒙受一键多值,而 NameObjectCollectionBase 只蒙受一键一值。
System.Collections.Specialized 定名空间中的一些强典范集合蕴含 StringCollection 和 StringDictionary,它们都包含彻底是字符串的值集合和字典。
CollectionsUtil 类提供一系列静态方法可以用来创建不区分巨细写的Hashtable或许SortedList集合的实例。
有些集合可以转换。比喻,HybridDictionary 类开初是 ListDictionary,增大后就变成 Hashtable。
别的,KeyedCollection<TKey, TItem> 是介于列表和字典之间的混杂典范,它提供了一种存储包含自己键的关于象的方法,当元素数量抵达指定阈值时,它也可以创建查找字典。
ListDictionary:运用单向链接列表实现 IDictionary。建议为但凡蕴含少于 10 个项目标集合,当数据项较少时,提供比Hashtable更好的机能。
LINQ to Objects 我们可运用 LINQ 查询来访问内存中的实现了System.Collections.IEnumerable 或许 System.Collections.Generic.IEnumerable<T> 接口关于象。
它提供了一种通用的数据访问情势;与标准 foreach 轮回比较,它但凡加倍简便,可读性更高;提供了强大的筛选、排序和分组功能。
若何决定 我们起重要清楚,如果存正在泛型版本,优先运用。
选择以前请先一定多少个标题:是否必要依次列访问,元素正在访问后维持?
访问的顺序是提高先辈先出或许落伍先出、随机访问?
是基于索引的访问,仍是基于键的访问?
是惟独值,仍是键值关于情势?
是一关于一,仍是一关于多?
是否允许重复?
是按进入的顺序保存,仍是必要按一定的规律排好序的,仍是无所谓?
是否必要更疾速度的检索和访问?