澳门葡京网上娱乐【转】C#集合类型大盘点

你还用过哪些其它的集合类,你还用过哪些其它的集合类

C#公家项目( Collections in C#)

C#公物项目( Collections in C#)

  集合是.NET FCL(Framework Class
Library)中格外关键的平片,也是咱们出中最常用到之功用之一,几乎是无处不在。俗话说知其然,知其所以然,平常看IEnumerable,IEnumerator,ICollection是免是明她们中各自的区别?除了List和Dictionary以外,你还用了什么样其它的集合类?废话少说,今天我们即便来拘禁有的这些概念集合类的接口及他们的兑现。

  集合是.NET FCL(Framework Class
Library)中充分重点之同片段,也是咱开中最常用到的法力有,几乎是无处不在。俗话说知其然,知其所以然,平常看IEnumerable,IEnumerator,ICollection是不是知他们中间各自的界别?除了List和Dictionary以外,你还因此了怎么其它的集合类?废话少说,今天我们就算来拘禁有些这些概念集合类的接口和她们之落实。

  • 集接口
  • 关联性泛型集合类
  • 未关联性泛型集合类
  • 推介使用状况
  • 非泛型集合类
  • 线程安全集合类
  • 会合接口
  • 关联性泛型集合类
  • 切莫关联性泛型集合类
  • 推荐使用状况
  • 非泛型集合类
  • 线程安全集合类

集结接口

  先来拘禁一下,FCL为咱提供了怎样接口:

  

汇接口

  先来拘禁一下,FCL为咱提供了如何接口:

  

IEnumerable 和IEnumberator

public interface IEnumerator
{

    bool MoveNext();
    object Current {  get; }
    void Reset();
}

  IEnumerator定义了咱遍历集合的为主方式,以便我们得实现只为前行的访集合中的诸一个素。而IEnumerable只发生一个法GetEnumerator即得到遍历器。

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

  注意:俺们经常用之foreach即是一律栽语法糖,实际上还是调用Enumerator里面的Current和MoveNext实现的遍历功能。

List<string> list = new List<string>() 
{ 
    "Jesse",
    "Chloe",
    "Lei",
    "Jim",
    "XiaoJun"
};

// Iterate the list by using foreach
foreach (var buddy in list)
{
    Console.WriteLine(buddy);
}

// Iterate the list by using enumerator
List<string>.Enumerator enumerator = list.GetEnumerator();
while (enumerator.MoveNext())
{
    Console.WriteLine(enumerator.Current);
}

  上面的代码中因故到之foreach和enumerator到IL中最终都见面为翻成enumerator的MoveNext和Current。

  IEnumerable是一个杀有因此之接口,实现其的利益包括:

  1. 支持foreach语句
  2. 当一个专业的集合类与任何类库进行互动
  3. 满足再复杂的汇聚接口的需求
  4. 支持集合初始化器

  当然实现之计吗闹成百上千,如下:

  1. 若是我们凑是透过包装其它集合类而来的,那么我们可以直接回这个集的enumerator
  2. 通过yield return 来返回
  3. 贯彻我们协调的IEnumerator来促成

  这里让大家演示一下怎么通过yield来贯彻返回enumerator

public class BuddyList : IEnumerable
{
    private string[] data= new string[]
    { 
        "Jesse",
        "Chloe",
        "Lei",
        "Jim",
        "XiaoJun"
    };

    public IEnumerator GetEnumerator()
    {
        foreach (var str in data)
        {
            yield return str;
        }
    }
}

var myBuddies= new BuddyList();
foreach (var str in myBuddies)
{
    Console.WriteLine(str);
}

  

IEnumerable 和IEnumberator

public interface IEnumerator
{

    bool MoveNext();
    object Current {  get; }
    void Reset();
}

  IEnumerator定义了俺们遍历集合的为主方法,以便我们得兑现只为前行的造访集合中之各级一个因素。而IEnumerable只生一个办法GetEnumerator即获得遍历器。

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

  注意:俺们常常用之foreach即是平栽语法糖,实际上还是调用Enumerator里面的Current和MoveNext实现之遍历功能。

List<string> list = new List<string>() 
{ 
    "Jesse",
    "Chloe",
    "Lei",
    "Jim",
    "XiaoJun"
};

// Iterate the list by using foreach
foreach (var buddy in list)
{
    Console.WriteLine(buddy);
}

// Iterate the list by using enumerator
List<string>.Enumerator enumerator = list.GetEnumerator();
while (enumerator.MoveNext())
{
    Console.WriteLine(enumerator.Current);
}

  上面的代码中之所以到之foreach和enumerator到IL中最后还见面叫翻成enumerator的MoveNext和Current。

  IEnumerable是一个不行有因此之接口,实现其的利益包括:

  1. 支持foreach语句
  2. 作一个正经的集合类与另外类库进行相互
  3. 满足再扑朔迷离的成团接口的急需
  4. 支撑集合初始化器

  当然实现之计吗来好多,如下:

  1. 设若我们凑是透过包装其它集合类而来的,那么我们得以一直回到这个集的enumerator
  2. 通过yield return 来返回
  3. 贯彻我们自己之IEnumerator来促成

  这里给大家演示一下争通过yield来贯彻返回enumerator

public class BuddyList : IEnumerable
{
    private string[] data= new string[]
    { 
        "Jesse",
        "Chloe",
        "Lei",
        "Jim",
        "XiaoJun"
    };

    public IEnumerator GetEnumerator()
    {
        foreach (var str in data)
        {
            yield return str;
        }
    }
}

var myBuddies= new BuddyList();
foreach (var str in myBuddies)
{
    Console.WriteLine(str);
}

  

ICollection<T>和ICollection

  从最上面第一摆设图我们得以掌握,ICollection是直接接轨自IEnumerable。而实在也是这样,我们可以说ICollection比IEnumerable多支持有成效,不仅仅只有提供基本的遍历功能,还包:

  1. 统计集合和要素个数
  2. 获得元素的下标
  3. 看清是否在
  4. 增补加元素到未尾
  5. 移除元素等等。。。

   ICollection 与ICollection<T>
略有不同,ICollection不提供编辑集合的职能,即Add和Remove。包括检查元素是否存在Contains也不支持。

ICollection<T>和ICollection

  从不过上面第一摆放图我们可以解,ICollection是直接接轨自IEnumerable。而实在也是这般,我们好说ICollection比IEnumerable多支持有功力,不仅仅只有提供基本的遍历功能,还连:

  1. 统计集合和因素个数
  2. 得到元素的下标
  3. 认清是否存在
  4. 加加元素到未尾
  5. 移除元素等等。。。

   ICollection 与ICollection<T>
略有不同,ICollection不提供编辑集合的效果,即Add和Remove。包括检查元素是否是Contains也未支持。

IList<T>和IList

  IList则是一直接轨自ICollection和IEnumerable。所以她包括双方的功能,并且支持因下标访问与加加元素。IndexOf,
Insert,
RemoveAt等等。我们可这么说,IEnumerable支持之功力最好少,只有遍历。而ICollection支持之力量稍微多一点,不仅有遍历还有保护这集的效应。而IList是最好咸的本子。

IList<T>和IList

  IList则是一直接轨自ICollection和IEnumerable。所以它们概括双方的功能,并且支持因下标访问同补充加元素。IndexOf,
Insert,
RemoveAt等等。我们得以这样说,IEnumerable支持的效力最好少,只有遍历。而ICollection支持的效果稍微多一些,不仅产生遍历还有维护这集的效应。而IList是最最全的版。

IReadOnlyList<T>

  这个是当Framework4.5受到新增的接口类型,可以叫看作是IList<T>的缩减版,去丢了独具或改变这个集的效能。比如:Add,
RemoveAt等等。

IReadOnlyList<T>

  这个是以Framework4.5蒙新增的接口类型,可以吃看成是IList<T>的缩减版,去丢了具备可能移这个集的法力。比如:Add,
RemoveAt等等。

IDictionary<TKey,TValue>

  IDictionary提供了针对性键值对聚集的拜访,也是延续了ICollection<T>和IEnumerable,扩展了通过Key来访问和操作数据的计。

IDictionary<TKey,TValue>

  IDictionary提供了对键值对聚集的拜访,也是延续了ICollection<T>和IEnumerable,扩展了经Key来访问与操作数据的点子。

关联性泛型集合类

  关联性集合类即我们常常说之键值对聚集,允许我们由此Key来访问和保安集合。我们先行来拘禁一下
FCL为我们提供了何等泛型的关联性集合类:

  1. Dictionary<TKey,TValue>
  2. SortedDictionary<TKey,TValue>
  3. SortedList<TKey,TValue>

关联性泛型集合类

  关联性集合类即我们常说之键值对聚集,允许我们经过Key来访问同掩护集合。我们事先来拘禁一下
FCL为咱提供了何等泛型的关联性集合类:

  1. Dictionary<TKey,TValue>
  2. SortedDictionary<TKey,TValue>
  3. SortedList<TKey,TValue>

Dictionary<TKey,TValue>

  Dictionary<TKey,TValue>可能是咱最常用之关联性集合了,它的访问,添加,删除数据所消费的时日是装有集合类里面最抢的,因为它里面用了Hashtable作为存储结构,所以不管存储了不怎么键值对,查询/添加/删除所花费的年月还是如出一辙的,它的日复杂度是O(1)。

  Dictionary<TKey,TValue>优势是寻觅插入速度快,那么什么是其的劣势呢?因为使用Hashtable作为存储结构,就象征中的多寡是无序排列的,所以想按部就班自然的依次去遍历Dictionary<TKey,TValue>里面的数目是若消费一点工夫的。

  作为TKey的类型必须贯彻GetHashCode()Equals() 或者提供一个IEqualityComparer,要不操作可能会见出现问题。

Dictionary<TKey,TValue>

  Dictionary<TKey,TValue>可能是咱最好常用的关联性集合了,它的访问,添加,删除数据所消费的时是有集合类里面太抢之,因为它其中用了Hashtable作为存储结构,所以管存储了聊键值对,查询/添加/删除所花费的日子都是平的,它的光阴复杂度是O(1)。

  Dictionary<TKey,TValue>优势是寻找插入速度快,那么什么是她的劣势呢?因为以Hashtable作为存储结构,就表示其中的多少是无序排列的,所以想以一定之逐条去遍历Dictionary<TKey,TValue>里面的数是设费一点时光的。

  作为TKey的种类必须贯彻GetHashCode()Equals() 还是提供一个IEqualityComparer,不然操作可能会见油然而生问题。

SortedDictioanry<TKey,TValue>

  SortedDictionary<TKey,TValue>和Dictionary<TKey,TValue>大致上是近乎之,但是于落实方式达成发生一点点组别。SortedDictionary<TKey,TValue>用二叉树作为存储结构的。并且依照key的顺序排列。那么这样的话SortedDictionary<TKey,TValue>的TKey就务须使促成IComparable<TKey>。假定想使迅速查询的又又能够好好的支持排序的言语,那便运SortedDictionary吧。

SortedDictioanry<TKey,TValue>

  SortedDictionary<TKey,TValue>和Dictionary<TKey,TValue>大致上是看似的,但是在贯彻方式上产生一点点分别。SortedDictionary<TKey,TValue>用二叉树作为存储结构的。并且按照key的顺序排列。那么这样的话SortedDictionary<TKey,TValue>的TKey就亟须使落实IComparable<TKey>。如果想要快速查询的而以会很好之支持排序的讲话,那便应用SortedDictionary吧。

SortedList<TKey,TValue>       

  SortedList<TKey,TValue>是外一个支撑排序的关联性集合。但是差之地方在,SortedList实际是以数据存存储于屡次组被的。也就是说添加和移除操作都是线性的,时间复杂度是O(n),因为操作间的元素或致有的数据移动。但是坐在检索的时段下了次私分查找,所以找的性会哼有的,时间复杂度是O(log
n)。所以推举下状况是如此地:如果您想如果快快搜索,又想凑按照key的顺序排列,最后是集的操作(添加同移除)比较少的话语,就是SortedList了。

SortedList<TKey,TValue>       

  SortedList<TKey,TValue>是外一个支撑排序的关联性集合。但是不同之地方在,SortedList实际是以数据存存储于屡次组吃之。也就是说添加和移除操作都是线性的,时间复杂度是O(n),因为操作间的元素或致有的数据移动。但是因为在搜寻的时节利用了第二分割查找,所以找的习性会好一些,时间复杂度是O(log
n)。所以推举应用状况是如此地:如果您想如果快速搜索,又想凑按照key的顺序排列,最后是集的操作(添加及移除)比较少的话语,就是SortedList了。

莫关联性泛型集合类

  非关联性集合就是无须key操作的一些集合类,通常咱们可就此元素本身或下标来操作。FCL主要也咱提供了以下几种植不关联性的泛型集合类。

  1. List<T>
  2. LinkedList<T>
  3. HashSet<T>
  4. SortedSet<T>
  5. Stack<T>
  6. Queue<T>

免关联性泛型集合类

  非关联性集合就是并非key操作的一对集合类,通常咱们可为此元素本身还是下标来操作。FCL主要也我们提供了以下几种不关联性的泛型集合类。

  1. List<T>
  2. LinkedList<T>
  3. HashSet<T>
  4. SortedSet<T>
  5. Stack<T>
  6. Queue<T>

List<T>

  泛型的List
类提供了非限定长度的集类型,List在中维护了必然长度的数组(默认新起长度是4),当我们插入元素的长度超过4要么开长度
的时段,会去还创设一个初的累组,这个新数组的长是开始长度的2加倍(不永远是2倍,当发现不断的而壮大的上,倍数会转换死),然后把原先的数组拷贝过来。所以只要掌握我们就要用这个集合装多少只要素的话,可以以开立的当儿指定初起值,这样就算避免了重的创新数组和拷贝值。

  另外的口舌由于中实质是一个数组,所以当List的未必添加多少是于快之,但是如果以数码的腔或中间添加去数据相对来说更不行一些缘会潜移默化其他数据的重新排列。

List<T>

  泛型的List
类提供了不限制长度的会师类型,List在中间维护了定长度的数组(默认新开始长度是4),当我们插入元素的长短逾4或开始长度
的上,会失掉又创设一个新的反复组,这个新数组的长度是起长度的2加倍(不永远是2倍,当发现不断的如扩大的时光,倍数会转换死),然后拿原先的数组拷贝过来。所以一旦知道我们将要用者集合装多少只因素的话,可以以开创的时刻指定初开始值,这样即便避免了再次的创办新数组和拷贝值。

  另外的语句由于中实质是一个屡次组,所以于List的不一定添加多少是较快之,但是一旦当数的头或者中间添加删减数据相对来说更不行一些因见面潜移默化外数据的重新排列。

LinkedList<T>

  LinkedList在里维护了一个双向的链表,也就是说我们当LinkedList的别样岗位添加或去数据其特性都是很快的。因为其不见面促成其他元素的位移。一般情况下List已经够我们下了,但是若对斯集在中间的丰富去操作特别累之言语,就建议使用LinkedList。

LinkedList<T>

  LinkedList于里维护了一个双向的链表,也就是说我们在LinkedList的别岗位添加或去除数据其性都是高速的。因为它不见面招其他元素的倒。一般情况下List已经足足我们下了,但是如果对这集在中游的丰富去操作十分累之说话,就建议以LinkedList。

HashSet<T>

  HashSet是一个无序的能够维持唯一性的汇聚。我们呢可以管HashSet看作是Dictionary<TKey,TValue>,只不过TKey和TValue都对准同一个对象。HashSet非常适合在我们用保障集合内元素唯一性但同时非需要按照顺序排列的上。

  HashSet不支持下标访问。

HashSet<T>

  HashSet是一个无序的会保持唯一性的聚集。我们也足以把HashSet看作是Dictionary<TKey,TValue>,只不过TKey和TValue都对同一个靶。HashSet非常适合在咱们要保障集合内元素唯一性但同时不待按照顺序排列的时节。

  HashSet不支持下标访问。

SortedSet<T>

  SortedSet和HashSet,就像SortedDictionary和Dictionary一样,还记及时有限独之别吗?SortedSet内部也是一个二叉树,用来支撑按梯次的排列元素。

SortedSet<T>

  SortedSet和HashSet,就像SortedDictionary和Dictionary一样,还记得及时片个之区别吗?SortedSet内部也是一个二叉树,用来支持以顺序的排元素。

Stack<T>

  后进先出的队
  不支持按下标访问

Stack<T>

  后进先出的队列
  不支持以下标访问

Queu<T>

  先进先出的行
  不支持以下标访问

Queu<T>

  先进先出的班
  不支持以下标访问

推荐应用状况

 

集合

顺序排列

连顺存储

直接访问方式

访问时间

操作时间

备注

Dictionary

 

Key

Key:

O(1)

 

O(1)

访问性能最快,不支持排序

SortedDinctionary

顺序排列

Key

Key: 
O(log n)

O(log n)

快速访问和支持排序的折衷

SortedList

顺序排列

Key

Key:

O(log n)

 

O(n)

和SortedDictionary相似,只是内部用数据替代树作为存储结构。

List

使用者可以精确控制元素的位置

Index

Index: O(1)

Value: O(n)

 

O(n)

最适合需要直接访问每一个元素的少量集合。

LinkedList

使用者可以精确控制元素的位置

不支持

Value:

O(n)

 

O(1)

最适合不需要直接访问单个元素,但是在集合中添加/移除非常频繁的场景。

HashSet

不支持

Key

Key:

O(1)

 

O(1)

能保持元素唯一性的集合。不支持排序

SortedSet

顺序排列

Key

Key:

O(log n)

 

O(log n)

能保持元素唯一性并且支持排序。

Stack

LIFO

只能获取顶部元素

Top: O(1)

O(1)

 

Queue

FIFO

只能获底部元素

Front: O(1)

O(1)

 

引进用状况

 

集合

顺序排列

连顺存储

直接访问方式

访问时间

操作时间

备注

Dictionary

 

Key

Key:

O(1)

 

O(1)

访问性能最快,不支持排序

SortedDinctionary

顺序排列

Key

Key: 
O(log n)

O(log n)

快速访问和支持排序的折衷

SortedList

顺序排列

Key

Key:

O(log n)

 

O(n)

和SortedDictionary相似,只是内部用数据替代树作为存储结构。

List

使用者可以精确控制元素的位置

Index

Index: O(1)

Value: O(n)

 

O(n)

最适合需要直接访问每一个元素的少量集合。

LinkedList

使用者可以精确控制元素的位置

不支持

Value:

O(n)

 

O(1)

最适合不需要直接访问单个元素,但是在集合中添加/移除非常频繁的场景。

HashSet

不支持

Key

Key:

O(1)

 

O(1)

能保持元素唯一性的集合。不支持排序

SortedSet

顺序排列

Key

Key:

O(log n)

 

O(log n)

能保持元素唯一性并且支持排序。

Stack

LIFO

只能获取顶部元素

Top: O(1)

O(1)

 

Queue

FIFO

只能获底部元素

Front: O(1)

O(1)

 

非泛型类集合

泛型集合类是以.NET2.0的下出来的,也就是说在1.0底时段是没这样便宜的物的。现在多我们都不利用这些集合类了,除非在开片暨老代码保持兼容的干活的时。来探望1.0时之.NET程序员们还有怎么样集合类可以就此。

  1. ArraryList

后来被List<T>替代。

  1. HashTable 后来被Dictionary<TKey,TValue>替代。
  2. Queue 后来被Queue<T>替代。
  3. SortedList 后来被SortedList<T>替代。
  4. Stack 后来被Stack<T>替代。

非泛型类集合

泛型集合类是以.NET2.0之当儿出来的,也就是说在1.0的时光是从未有过这么便宜之东西的。现在基本上我们就休采取这些集合类了,除非在开一些和老代码保持兼容的劳作的时刻。来看看1.0时的.NET程序员们还生安集合类可以就此。

  1. ArraryList

后来被List<T>替代。

  1. HashTable 后来被Dictionary<TKey,TValue>替代。
  2. Queue 后来被Queue<T>替代。
  3. SortedList 后来被SortedList<T>替代。
  4. Stack 后来被Stack<T>替代。

线程安全的集合类

  1. ConcurrentQueue 线程安全本的Queue
  2. ConcurrentStack线程安全本的Stack
  3. ConcurrentBag线程安全的对象集合
  4. ConcurrentDictionary线程安全之Dictionary
  5. BlockingCollection

.NET也咱提供的集合类是我们大常用之工具类之一,希望这首文章会助大家还好的认识这些集合类。当然,个人感觉还产生无全面的地方,比如说HashTable和Binary
Search
Tree就没有细究下去,包括但为链表和双向链表之间的比本文为没有提及。感兴趣之恋人可以深入摸底一下。

 

线程安全的集合类

  1. ConcurrentQueue 线程安全本的Queue
  2. ConcurrentStack线程安全本的Stack
  3. ConcurrentBag线程安全之靶子集合
  4. ConcurrentDictionary线程安全的Dictionary
  5. BlockingCollection

.NET为我们提供的集合类是我们老常用之工具类之一,希望这首稿子会帮助大家再次好的认识这些集合类。当然,个人感觉还来非全面的地方,比如说HashTable和Binary
Search
Tree就无细究下去,包括但为链表和双向链表之间的对比本文为从来不提及。感兴趣的冤家可以深入了解一下。