重庆熊猫 Loading

.NET教程 - 集合(Collection)

更新记录
转载请注明出处:
2022年9月30日 发布。
2022年9月29日 从笔记迁移到博客。

基础

集合定义

集合(Collection)类是专门用于数据存储和检索的类

集合的作用

集合本质是一种数据结构,用于存储数据

常见数据来源

来自数据库、XML文件、文本文件、用户输入、网络API调用等

集合分类

Interfaces that define standard collection protocols

Base classes for writing application-specific collections

Ready-to-use collection classes (lists, dictionaries, etc)

主要命名空间:

System.Collections //非泛型集合Nongeneric collections

System.Collections.Generic //泛型集合Generic collections

System.Collections.Specialized //特定类型专用 Strongly typed collections

System.Collections.ObjectModel // Bases for your own collections

System.Collections.Concurrent //线程安全集合Thread-safe collection

相同点: 都是数据结构用于存储数据

不同点: 泛型集合只能保存固定类型,类型更加安全、效率更高

​ 非泛型集合可以存储多种类型,类型不安全、效率低

非泛型集合类

非泛型集合类定义在System.Collections命名空间下

类名 描述
ArrayList 与数组类型类似的一种集合,可以动态的改变集合元素的数量
Stack 后进先出(Last In Frist Out,LIFO)类型集合
Queue 先进先出(Frist In First Out,FIFO)类型集合
HashTable 键(key)/值(value)对集合,键值对根据键值的哈希进行组织
SortedList 类似HashTable,但是经过排序,可以通过键或索引进行访问值
BitArray 二进制位量集合

注意:非泛型版本集合类型,存在效率低和类型不安全问题

使用场景:需要兼容老旧的不支持泛型类型的场景

泛型集合类

泛型集合类定义在System.Collections.Generic命名空间下

类名 描述

带通知事件的集合类

带通知事件的集合类定义在System.Collections.ObjectModel;命名空间下

类名 描述

ObservableCollection 集合改动时发出通知事件

ReadOnlyObservableCollection 集合改动时发出通知事件的只读版本

线程安全集合类

类名 描述

特殊类型集合类

命名空间:System.Collections.Specialized

类名 描述
BitVector32 包含32个位的集合类

集合初始化器

简单值初始化

List<int> s = new List<int> { 1, 2, 3, 4, 5 };

Dictionary初始化-字典集合初始化器(Collection Initializers)。

// C# 6.0以前版本
Dictionary<string, Product> products = new Dictionary<string, Product> {
    { "Kayak", new Product { Name = "Kayak", Price = 275M } },
    { "Lifejacket", new Product{ Name = "Lifejacket", Price = 48.95M } }
};

Dictionary<string, ConsoleColor> colorMap = 
    new Dictionary<string, ConsoleColor>
    {
        { "Error", ConsoleColor.Red },
        { "Warning", ConsoleColor.Yellow },
        { "Information", ConsoleColor.Green },
        { "Verbose", ConsoleColor.White}
    };

新版C#支持Dictionary索引初始化器( Index Initializer)。

// C# 6.0 以及以后版本
Dictionary<string, ConsoleColor> colorMap = 
    new Dictionary<string, ConsoleColor>
    {
        ["Error"] = ConsoleColor.Red,
        ["Warning"] = ConsoleColor.Yellow,
        ["Information"] = ConsoleColor.Green,
        ["Verbose"] = ConsoleColor.White
    };

Dictionary<string, Product> products = new Dictionary<string, Product>
{
    ["Kayak"] = new Product { Name = "Kayak", Price = 275M },
    ["Lifejacket"] = new Product { Name = "Lifejacket", Price = 48.95M }
};

只要支持索引器的集合都可以使用这种方式初始化。

var dict = new Dictionary<int, string>()
{
  [3] = "three",
  [10] = "ten"
};

集合性能表

集合 Add Insert Remove Item Sort Find
List O(1)、 O(0) O(n) O(n) O(1) O(nLogn),最坏O(n2) O(n)
Stack O(1)、 O(0) N/A Pop, O(1) N/A N/A N/A
Queue O(1)、 O(0) N/A Dequque,O(1) N/A N/A N/A
HashSet O(1)、 O(0) AddO(1) 或 O(1) O(1) N/A N/A N/A
SortedSet O(1)、 O(0) AddO(1) 或 O(1) O(1) N/A N/A N/A
LinkedList AddLast O(1) AddAfter O(1) O(1) N/A N/A O(n)
Dictionary <TKey,TValue> O(1)、 O(0) N/A O(1) O(1) N/A N/A
SortedDictionary <TKey, TValue> O(log n) N/A O(log n) O(log n) N/A N/A
SortedList <TKey, TValue> O(n) N/A O(n) 读写O(log n) O(n) N/A N/A

集合变量初始化最佳实践

不要用NULL表示空集合,最好初始化为空集合

考虑使用Enumerable.Empty()方法进行初始化

集合主要接口

说明

IEnumerable接口,所有的非泛型集合都实现了该接口,可以使用foreach进行遍历

ICollection接口

常见集合接口图

image

常见集合接口

image

IEnumerable (and IEnumerable)提供集合可枚举功能

ICollection 和 ICollection提供集合的基础功能

IDictionary 和 IDictionary提供

IList 和 IList 提供

注意: ICollection does not extend ICollection

​ IList does not extend IList

​ IDictionary<TKey, TValue> does not extend IDictionary

IEnumerable和IEnumerable接口

可枚举和枚举器(IEnumerable and IEnumerator)

集合有不同的形态

从简单的数组(Array)、链表(linked lists)到复杂的红黑树(red/black trees)

每种类型的集合都有有各自的方法进行遍历成员

为了实现使用一个统一的方式进行遍历成员

于是.NET 框架中出现了IEnumerable可迭代接口 和 IEnumerator枚举器

本质是设计模式中的迭代模式,使用统一的接口来实现遍历各种集合

如果将集合用于foreach语句,就要实现IEnumerable或IEnumerable接口

实现该接口可以使用foreach迭代集合中的项

接口内定义了GetEnumerator方法

IEnumerator接口定义如下

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

IEnumerator接口定义如下

public interface IEnumerator<T> : IEnumerator, IDisposable
{
    T Current { get; }
}

IEnumerable接口定义如下

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

IEnumerable接口定义如下

public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

Class Diagram of IEnumerator and IEnumerator Interfaces

image

IEnumerator和IEnumerator接口

ICollection和ICollection接口

作用:

可以获得集合中项的个数,并能把项复制到另一个简单的数组类型中

get size of the collection、access a member by index、search、modify the collection

该接口内的属性和方法:

Count属性: 获得当前集合中元素的数量

IsSynchronized属性: 访问集合的线程是否安全返回布尔类型的值

SyncRoot属性: 返回同步集合的对象

Add()方法: 添加元素到集合之中

Remove()方法: 从集合中移除元素

Clear()方法: 清空集合中的所有元素

CopyTo(Array array, int index)方法:将指定的索引值之后的元素复制到数组之中

ICollection 接口定义:

public interface ICollection<T> : IEnumerable<T>, IEnumerable
{
    int Count { get; }
    bool Contains (T item);
    void CopyTo (T[] array, int arrayIndex);
    bool IsReadOnly { get; }
    void Add(T item);
    bool Remove (T item);
    void Clear();
}

ICollection 接口定义

public interface ICollection : IEnumerable
{
    int Count { get; }
    bool IsSynchronized { get; }
    object SyncRoot { get; }
    void CopyTo (Array array, int index);
}

IList和IList接口

继承自IEnumerable接口和ICollection接口

用于通过指定位置的索引访问元素

该接口内定义了一个索引器
image

该接口内的属性和方法:

​ Insert(): 插入元素到集合中

​ RemoveAt(): 移除集合指定位置的元素

List是按元素添加的顺序进行排列的,如果需要自定义排序

可以使用Sort()方法

IList 接口定义

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
{
    T this[int index] { get; set; }
    int IndexOf(T item);
    void Insert(int index, T item);
    void RemoveAt(int index);
}

IList 接口定义

public interface IList : ICollection, IEnumerable
{
    object this [int index] { get; set }
    bool IsFixedSize { get; }
    bool IsReadOnly { get; }
    int Add (object value);
    void Clear();
    bool Contains (object value);
    int IndexOf (object value);
    void Insert (int index, object value);
    void Remove (object value);
    void RemoveAt (int index);
}

List实例

using System;
using System.Collections.Generic;

class Program
{
  static void Main()
  {
      List<string> list = new List<string>()
      { "Sneezy", "Happy", "Dopey",  "Doc", "Sleepy", "Bashful",  "Grumpy"};
      list.Sort();

      Console.WriteLine(
          $"In alphabetical order { list[0] } is the "
          + $"first dwarf while { list[6] } is the last.");

      list.Remove("Grumpy");
  }
}

IReadOnlyCollection 接口

用于只读集合

IReadOnlyCollection 接口的定义

public interface IReadOnlyCollection<out T> : IEnumerable<T>, IEnumerable
{
    int Count { get; }
}

IReadOnlyList 接口

只读列表接口,常用于对外暴露List,只用于读取使用

IReadOnlyList 接口的定义

public interface IReadOnlyList<out T> : IReadOnlyCollection<T>, 
IEnumerable<T>, IEnumerable
{
    T this[int index] { get; }
}

ISet接口

ISet派生自ICollection接口

该接口通常用于集实现

IDictionary和IDictionary<Tkey,Tvalue>接口

继承自IEnumerable接口和ICollection接口

类似IList接口

提供了可通过键值访问项的能力

IDictionary接口与IDictionary<TKey,TValue>接口的不同之处在于:

IDictionary Retrieving a nonexistent key via the indexer returns null

IDictionary<TKey,TValue> Retrieving a nonexistent key via the indexer throwing an exception

IDictionary Contains tests for membership rather than ContainsKey

使用的键值对类型不同,IDictionary使用struct DictionaryEntry类型

IDictionary<TKey,TValue>接口定义

public interface IDictionary <TKey, TValue> :ICollection <KeyValuePair <TKey, TValue>>, IEnumerable
{
   bool ContainsKey (TKey key);
   bool TryGetValue (TKey key, out TValue value);
   void Add         (TKey key, TValue value);
   bool Remove      (TKey key);

   TValue this [TKey key]      { get; set; }  // Main indexer - by key
   ICollection <TKey> Keys     { get; }       // Returns just keys
   ICollection <TValue> Values { get; }       // Returns just values
}

IReadOnlyDictionary<TKey,TValue>接口

IList 和 IDictionary<TKey, TValue> 对比

IList的元素基于位置(Position)

IDictionary的元素基于键(Key)

KeyValuePair <TKey, TValue>

KeyValuePair <TKey, TValue>定义

public struct KeyValuePair <TKey, TValue>
{
  public TKey Key     { get; }
  public TValue Value { get; }
}

ILookUp<TKey, TValue>接口

类似IDictionary<Tkey,Tvalue>

IComparer接口

包含Compare()方法,可以给集合进行排序

IEqualityComparer接口

对集合进行比较排序

CollectionBase类

System.Collections.CollectionBase类

实现自定义集合可以继承该类

DictionaryBase类

IEnumerable 和 IDisposable

IEnumerable接口继承了IDisposable接口

这样可以让枚举器实现释放非托管资源

foreach语句是语法糖,会将语句转为枚举器调用形式并最后调用IDisposable接口

实例:

foreach (var element in somethingEnumerable)
{ ... }
//as same
using (var rator = somethingEnumerable.GetEnumerator())
while (rator.MoveNext())
{
    var element = rator.Current;
    ...
}

实例

字符串类型使用预定义的枚举器

string panda = "Panda";
var enumerator = panda.GetEnumerator();
string temp;
while (enumerator.MoveNext())
{
    temp = enumerator.Current.ToString() + ".";
    Console.Write(temp);
}
enumerator.Reset();

数组类型使用预定义的枚举器

int[] data = { 1, 2, 3 };
var rator = ((IEnumerable<int>)data).GetEnumerator();

自定义类型实现枚举器(IEnumerable)

public class MyIntList : IEnumerable
{
    int[] data = { 1, 2, 3 };
    public IEnumerator GetEnumerator() => new Enumerator (this);
    class Enumerator : IEnumerator // Define an inner class
    { // for the enumerator.
        MyIntList collection;
        int currentIndex = -1;
        public Enumerator (MyIntList items) => this.collection = items;
        public object Current
        {
            get
            {
                if (currentIndex == -1)
                    throw new InvalidOperationException ("Enumeration not started!");
                if (currentIndex == collection.data.Length)
                    throw new InvalidOperationException ("Past end of list!");
                return collection.data [currentIndex];
            }
        }
        public bool MoveNext()
        {
            if (currentIndex >= collection.data.Length - 1) return false;
            return ++currentIndex < collection.data.Length;
        }
        public void Reset() => currentIndex = -1;
    }
}

自定义类型实现枚举器(IEnumerable

class MyIntList : IEnumerable<int>
{
    int[] data = { 1, 2, 3 };
    // The generic enumerator is compatible with both IEnumerable and
    // IEnumerable<T>. We implement the nongeneric GetEnumerator method
    // explicitly to avoid a naming conflict.
    public IEnumerator<int> GetEnumerator() => new Enumerator(this);
    IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this);
    class Enumerator : IEnumerator<int>
    {
        int currentIndex = -1;
        MyIntList collection;
        public Enumerator(MyIntList items) => this.items = items;
        public int Current => collection.data[currentIndex];
        object IEnumerator.Current => Current;
        public bool MoveNext() => ++currentIndex < collection.data.Length;
        public void Reset() => currentIndex = -1;
        // Given we don't need a Dispose method, it's good practice to
        // implement it explicitly, so it's hidden from the public interface.
        void IDisposable.Dispose() { }
    }
}

使用IComparable<>实现自定义类型排序

using System;
using System.Collections.Generic;

namespace Test
{
    class Animal:IComparable<Animal>
    {
        public int Code { get; set; }
        public string Name { get; set; }

        public Animal(int code, string name)
        {
            this.Code = code;
            this.Name = name;
        }

        public int CompareTo(Animal other)
        {
            if(this.Code >= other.Code)
            {
                return 1;
            }
            else
            {
                return -1;
            }
        }
    }
    class TestClass
    {
        public static void Main()
        {
            //新建集合
            List<Animal> animals = new List<Animal>();
            //添加元素
            animals.Add(new Animal(666, "Panda"));
            animals.Add(new Animal(222, "Dog"));
            animals.Add(new Animal(333, "Cat"));
            //排序
            animals.Sort();

            //打印输出
            foreach (Animal item in animals)
            {
                Console.WriteLine($"{item.Code}-{item.Name}");
            }

            Console.ReadKey();
        }
    }
}

集合元素的比较和排序(Plugging in Equality and Order)

说明

集合中的元素如果需要比较和排序,元素本身需要实现一些接口

实现元素的Equals and GetHashCode方法,以便Dictionery和HashTable使用

实现 IComparable/IComparable 接口,以便排序集合使用

实现IEqualityComparer and IEqualityComparer接口执行比较

常用于Hashtable and Dictionary

主要接口

IEqualityComparer and IEqualityComparer

说明

Performs plug-in equality comparison and hashing

Recognized by Hashtable and Dictionary

接口的定义

IEqualityComparer and IEqualityComparer

public interface IEqualityComparer<T>
{
   bool Equals (T x, T y);
   int GetHashCode (T obj);
}

public interface IEqualityComparer     // Nongeneric version
{
   bool Equals (object x, object y);
   int GetHashCode (object obj);
}

IComparer and IComparer

说明

Performs plug-in order comparison

Recognized by the sorted dictionaries and collections; also, Array.Sort

两个接口的区别:

IComparable用于将自己与同类型的另一个实例进行比较

IComparer用于比较给定的类型的2个变量

接口的定义

IComparable接口的定义

using System;
public interface IComparable<in T>
{
    int CompareTo([AllowNull] T other);
}


IComparer接口的定义

using System.Collections.Generic;
public interface IComparer<in T>
{
    int Compare([AllowNull] T x, [AllowNull] T y);
}

实例

实现自定义比较

public class Customer
{
  public string LastName;
  public string FirstName;

  public Customer (string last, string first)
  {
    LastName = last;
    FirstName = first;
  }
}

public abstract class EqualityComparer<T> : IEqualityComparer,
                                            IEqualityComparer<T>
{
  public abstract bool Equals (T x, T y);
  public abstract int GetHashCode (T obj);

  bool IEqualityComparer.Equals (object x, object y);
  int IEqualityComparer.GetHashCode (object obj);

  public static EqualityComparer<T> Default { get; }
}

public class LastFirstEqComparer : EqualityComparer <Customer>
{
  public override bool Equals (Customer x, Customer y)
    => x.LastName == y.LastName && x.FirstName == y.FirstName;

  public override int GetHashCode (Customer obj)
    => (obj.LastName + ";" + obj.FirstName).GetHashCode();
}

var eqComparer = new LastFirstEqComparer();
var d = new Dictionary<Customer, string> (eqComparer);
d [c1] = "Joe";
Console.WriteLine (d.ContainsKey (c2));         // True

自定义字典的相等(Customizing Dictionary Equality)

IEqualityComparer接口

public interface IEqualityComparer<in T>
{
    bool Equals([AllowNull] T x, [AllowNull] T y);
    int GetHashCode([DisallowNull] T obj);
}

定义比较的注意点

Equal objects must have equal hash codes

The hash code of an object should not change for the life of the instance (at least while it is in the hash table)

The hashing algorithm should quickly produce a well-distributed hash

The hashing algorithm should avoid throwing exceptions in all possible object states

实例:自定义相等比较

class ContactEquality : IEqualityComparer<Contact>
{
  public bool Equals(Contact? x, Contact? y)
  {
      if (Object.ReferenceEquals(x, y))
          return true;
      if (x == null || y == null)
          return false;
      return x.LastName == y.LastName &&
          x.FirstName == y.FirstName;
  }

  public int GetHashCode(Contact x)
  {
      if (x is null)
          return 0;
      int h1 = x.FirstName == null ? 0 : x.FirstName.GetHashCode();
      int h2 = x.LastName == null ? 0 : x.LastName.GetHashCode();
      return h1 * 23 + h2;
  }
}

实例:将自定义相等比较设置到Dictionary上

new Dictionary<Contact, string>(new ContactEquality)

不可变集合(Immutable Collections)

说明

所有不可变集合
image

不可变集合的优点(适合场景)

Immutability allows for easy concurrency and parallelization

部分场景下性能更优

创建不可变集合

使用.Create()静态方法

使用.ToImmutable方法,从可变类型转为不可变类型

使用.CreateBuilder()创建Builders来初始化

注意:在不可变集合上调用可变方法会导致返回新的不可变集合,效率非常低下

实例:使用.Create()静态方法-创建不可变Array

ImmutableArray<int> array = ImmutableArray.Create<int> (1, 2, 3);

实例:从可变类型转为不可变类型

var list = new[] { 1, 2, 3 }.ToImmutableList();

实例:创建Builder来实例化-创建不可变Array

ImmutableArray<int>.Builder builder = ImmutableArray.CreateBuilder<int>();
builder.Add (1);
builder.Add (2);
builder.Add (3);
builder.RemoveAt (0);
ImmutableArray<int> myImmutable = builder.ToImmutable();

实例:已有的不可变集合创建Builder

var builder2 = myImmutable.ToBuilder();
builder2.Add (4); // Efficient
builder2.Remove (2); // Efficient
... // More changes to builder...
// Return a new immutable collection with all the changes applied:
ImmutableArray<int> myImmutable2 = builder2.ToImmutable();

CollectionBase

ArrayList

说明

类似数组类型,保存的都是Object对象,使用时需要进行拆箱

无长度限制

动态数组,可以动态增减元素,不用手动分配大小

Array 和 ArrayList 区别

Array:

  1. Fixed Length
  2. Cannot insert into the middle
  3. Cannot delete from middle

ArrayList:

  1. Variable Length
  2. Can insert an element into the middle of the collection
  3. Can delete element from the middle of the collection

初始化

//无参数实例化
ArrayList list1 = new ArrayList();
//使用ICollection实例对象进行实例化
ArrayList list2 = new ArrayList(list1);
//使用指定容量进行实例化
ArrayList list3 = new ArrayList(5);

操作

添加元素到集合

ArrayList list1 = new ArrayList();
list1.Add(666);
list1.Add("Panda");
list1.Add('P');
list1.Add(new int[] { 1 });
Console.WriteLine(list1.Count);

从指定的索引处添加一个集合元素(插入)

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
list1.Insert(0, 666);

从指定的索引处添加一个集合(插入范围)

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
list1.InsertRange(1, new int[] { 1, 2, 3 });

从集合移除一个元素通过指定值

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
list1.Remove(2);

从集合移除一个元素通过指定索引

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
list1.RemoveAt(0);

从集合移除元素通过指定索引范围

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
list1.RemoveRange(0, 2);

清空集合所有元素

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Clear();

检测是否包含指定的元素

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
Console.WriteLine(list1.Contains(2));
Console.WriteLine(list1.Contains(3));

复制集合

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);

object[] resultArray = new object[10];
list1.CopyTo(resultArray);

foreach (var item in resultArray)
{
    Console.Write(item);
    Console.Write(" ");
}

复制集合中的元素到数组中

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
object[] resultArray = new object[10];
//转为System.Array[]类型
int[] arr1 = (int[])list1.ToArray(typeof(int));
//转为Object[]类型
object[] arr2 = list1.ToArray();

查找指定元素值第一次出现的索引

注意:没有查找到返回-1

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
//直接查找
list1.IndexOf(3);
//并指定起始值
list1.IndexOf(3,0);
//并指定查找数量
list1.IndexOf(3,0,list1.Count);

查找指定元素值最后第一次出现的索引

注意:没有查找到返回-1

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
//直接查找
list1.LastIndexOf(3);
//并指定起始值
list1.LastIndexOf(3,0);
//并指定查找数量
list1.LastIndexOf(3,0,list1.Count);

获得当前元素的数量

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
Console.WriteLine(list1.Count);

获得和设置预设的集合元素数量

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);
Console.WriteLine(list1.Capacity); //4
list1.Capacity = 123;
Console.WriteLine(list1.Capacity); //123

使用for遍历ArrayList

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);

for (int i = 0; i < list1.Count; i++)
{
    Console.WriteLine(list1[i]);
}

使用foreach遍历ArrayList

ArrayList list1 = new ArrayList();
list1.Add(1);
list1.Add(2);
list1.Add(3);

foreach (var item in list1)
{
    Console.WriteLine(item);
}

ArrayList转为List

注意:需要System.Linq命名空间

using System.Linq;
ArrayList arrayList = new ArrayList();
arrayList.Add("Panda");
arrayList.Add("Dog");
List<string> result = arrayList.Cast<string>().ToList();
foreach (string item in result)
{
    Console.WriteLine(item);
}

ArrayList转为Array

ArrayList arrayList = new ArrayList();
arrayList.Add("Panda");
arrayList.Add("Dog");
//转为数组
string[] result = (string[])arrayList.ToArray();
foreach (string item in result)
{
    Console.WriteLine(item);
}

Stack

说明

后进先出(Last In Frist Out,LIFO)类型

初始化

//直接无参数初始化
Stack stack1 = new Stack();
//使用ICollection实例初始化
Stack stack2 = new Stack(new int[] { 1, 2, 3 });
//使用容量值初始化
Stack stack3 = new Stack(66);

操作

进栈

Stack stack1 = new Stack(new int[] { 1, 2, 3 });
stack1.Push(1);

出栈

Stack stack1 = new Stack(new int[] { 1, 2, 3 });
Console.WriteLine(stack1.Pop());

获得栈顶元素

Stack stack1 = new Stack(new int[] { 1, 2, 3 });
Console.WriteLine(stack1.Peek());

获得当前容量

Stack stack1 = new Stack(new int[] { 1, 2, 3 });
Console.WriteLine(stack1.Count);

检测是否包含元素值

Stack stack1 = new Stack(new int[] { 1, 2, 3 });
Console.WriteLine(stack1.Contains(3));

清空栈

Stack stack1 = new Stack(new int[] { 1, 2, 3 });
stack1.Clear();

转为数组

Stack stack1 = new Stack(new int[] { 1, 2, 3 });
object[] test = stack1.ToArray();

复制

Stack stack1 = new Stack(new int[] { 1, 2, 3 });
int[] resultArray = new int[10];
stack1.CopyTo(resultArray,2);

遍历

Stack stack1 = new Stack(new int[] { 1, 2, 3 });
foreach (var item in stack1)
{
    Console.WriteLine(item);
}

Queue

说明

先进先出(First In Last Out,FIFO)类型

初始化

//直接无参数初始化
Queue queue1 = new Queue();
//使用ICollection实例初始化
Queue queue2 = new Queue(new int[] { 1, 2, 3 });
//使用容量值初始化
Queue queue3 = new Queue(66);

操作

进队

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
queue1.Enqueue(1);

出队

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
Console.WriteLine(queue1.Dequeue());

获得队首元素值

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
Console.WriteLine(queue1.Peek());

检测包含

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
Console.WriteLine(queue1.Contains(1));

获得元素当前容量

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
Console.WriteLine(queue1.Count);

清空队列

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
queue1.Clear();

转为数组

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
object[] test = queue1.ToArray();

复制

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
object[] test2 = new object[10];
queue1.CopyTo(test2,2);

遍历

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
foreach (var item in queue1)
{
    Console.WriteLine(item);
}

容量转为当前实际容量

Queue queue1 = new Queue(new int[] { 1, 2, 3 });
queue1.TrimToSize();

HashTable

说明

键值对元素集合

Hashtable is nongeneric version of Dictionary<TKey,TValue>

初始化

//直接无参数初始化
Hashtable hashtable1 = new Hashtable();
//使用ICollection实例初始化
SortedList sortedList = new SortedList();
Hashtable hashtable2 = new Hashtable(sortedList);
//使用容量值初始化
Hashtable hashtable3 = new Hashtable(66);

操作

添加元素到集合

Hashtable hashtable1 = new Hashtable();
hashtable1.Add("Panda", 666);

从集合移除元素

Hashtable hashtable1 = new Hashtable();
hashtable1.Remove("Panda");

获得当前元素的数量

Hashtable hashtable1 = new Hashtable();
hashtable1.Contains("Panda");

索引访问元素成员

获得集合键集合

Hashtable hashtable1 = new Hashtable();
foreach (var item in hashtable1.Keys)
{
    Console.WriteLine(item);
}

获得集合值集合

Hashtable hashtable1 = new Hashtable();
foreach (var item in hashtable1.Values)
{
    Console.WriteLine(item);
}

检测集合是否包含指定键

Hashtable hashtable1 = new Hashtable();
hashtable1.ContainsKey("Panda");

检测集合是否包含指定值

Hashtable hashtable1 = new Hashtable();
hashtable1.ContainsValue(666);

清空集合

Hashtable hashtable1 = new Hashtable();
hashtable1.Clear();

复制集合

Hashtable hashtable1 = new Hashtable();
object[] testArr = new object[10];
hashtable1.CopyTo(testArr, 2);

遍历

Hashtable hashtable1 = new Hashtable();
hashtable1.Add("Panda", 666);
foreach (var item in hashtable1)
{
    Console.WriteLine(((DictionaryEntry)item).Key);
    Console.WriteLine(((DictionaryEntry)item).Value);
}

SortedList

说明

类似Hashtable,但SortedList会对元素进行排序根据元素的键

初始化

//直接无参数初始化
SortedList sortedList1 = new SortedList();
//使用ICollection实例初始化
Hashtable hashtable = new Hashtable();
SortedList sortedList2 = new SortedList(hashtable);
//使用容量值初始化
SortedList sortedList3 = new SortedList(66);

操作

添加新元素到集合

SortedList sortedList1 = new SortedList();
sortedList1.Add("Panda", 666);
sortedList1.Add("Dog", 888);

移除指定键元素

SortedList sortedList1 = new SortedList();
sortedList1.Remove("Panda");

移除指定索引元素

SortedList sortedList1 = new SortedList();
sortedList1.RemoveAt(0);

清空集合所有元素

SortedList sortedList1 = new SortedList();
sortedList1.Clear();

获得指定索引的元素键

SortedList sortedList1 = new SortedList();
Console.WriteLine(sortedList1.GetKey(0));

获得指定索引的元素值

SortedList sortedList1 = new SortedList();
Console.WriteLine(sortedList1.GetByIndex(0));

获得当前集合元素数量

SortedList sortedList1 = new SortedList();
Console.WriteLine(sortedList1.Count);

获得集合中所有键组成的集合

SortedList sortedList1 = new SortedList();
foreach (var item in sortedList1.Keys)
{
}

获得集合中所有值组成的集合

SortedList sortedList1 = new SortedList();
foreach (var item in sortedList1.Values)
{
}

检测指定键是否存在

SortedList sortedList1 = new SortedList();
sortedList1.Contains("Panda");
Console.WriteLine(sortedList1.ContainsKey("Panda"));

检测指定值是否存在

SortedList sortedList1 = new SortedList();
Console.WriteLine(sortedList1.ContainsValue(666));

获得指定元素键的索引值

SortedList sortedList1 = new SortedList();
Console.WriteLine(sortedList1.IndexOfKey("Panda"));

获得指定元素值的索引值

SortedList sortedList1 = new SortedList();
Console.WriteLine(sortedList1.IndexOfValue(666));

裁剪容量到目前元素容量

SortedList sortedList1 = new SortedList();
sortedList1.TrimToSize();

获得和设置预设容量大小

SortedList sortedList1 = new SortedList();
Console.WriteLine(sortedList1.Capacity);
sortedList1.Capacity = 123;

集合复制到数组

SortedList sortedList1 = new SortedList();
object[] testArray = new object[10];
sortedList1.CopyTo(testArray,2);

检测是否固定大小集合

SortedList sortedList1 = new SortedList();
Console.WriteLine(sortedList1.IsFixedSize);

遍历

SortedList sortedList1 = new SortedList();
sortedList1.Add("Panda", 666);
foreach (var item in sortedList1)
{
    Console.WriteLine(((DictionaryEntry)item).Key);
    Console.WriteLine(((DictionaryEntry)item).Value);
}

BitArray

说明

元素的值为0或者1的集合
dynamically sized collection of compacted bool values
only one bit for each value

执行位运算操作

bitwise operator methods And, Or, Xor, and Not

实例:进行位运算

//测试使用的bitArray1
BitArray bitArray1 = new BitArray(5);
bitArray1[0] = true;
bitArray1[1] = false;
bitArray1[2] = true;
//测试使用的bitArray2
BitArray bitArray2 = new BitArray(5);
bitArray1[0] = true;
bitArray1[1] = false;
bitArray1[2] = true;
//进行位运算
BitArray result1 = bitArray1.And(bitArray2);
BitArray result2 = bitArray1.Xor(bitArray2);
BitArray result3 = bitArray1.Or(bitArray2);
BitArray result4 = bitArray1.Not();
//左移动操作
bitArray1.LeftShift(2);
//右移动操作
bitArray1.RightShift(2);

实例

增加元素

BitArray bitArray1 = new BitArray(5);
bitArray1.Set(0, true);
//设置所有值位true
bitArray1.SetAll(true);

List

说明

列表集合

实例

初始化列表

List<int> list = new List<int>() { 1, 2, 3, 4 };

注意:在转为的IL代码中实际上使用的是Add方法

设置/获得列表的容量

List<int> list = new List<int>();
//获得容量
Console.WriteLine(list.Capacity);
//设置容量
list.Capacity = 120;

去除不需要的容量(容量设置为实际元素数量)

List<int> list = new List<int>();
list.TrimExcess();

获得当前列表中元素的个数

List<int> list = new List<int>();
Console.WriteLine(list.Count);

添加元素到列表中

List<int> list = new List<int>();
//添加元素到列表中
list.Add(1);
list.Add(2);
list.Add(3);

添加多个元素到列表中

List<int> list = new List<int>();
//添加多个元素到列表中
list.AddRange(new List<int> { 4, 5, 6 });

遍历列表

List<int> list = new List<int>();
//遍历列表
foreach (var item in list)
{
    Console.WriteLine(item);
}

使用索引访问元素

List<int> list = new List<int>(){1, 2, 3, 4, 5, 6};
//使用索引访问元素
Console.WriteLine(list[0]);
Console.WriteLine(list[3]);

移除指定索引的元素

List<int> list = new List<int>(){1, 2, 3, 4, 5, 6};
//移除指定索引的元素
list.RemoveAt(0);

移除指定内容的元素

List<int> list = new List<int>(){1, 2, 3, 4, 5, 6};
//移除指定内容的元素
list.Remove(5);

移除指定范围的元素

List<int> list = new List<int>(){1, 2, 3, 4, 5, 6};
//移除指定范围的元素
list.RemoveRange(0, 2);

检测元素存在

List<int> list = new List<int>(){1, 2, 3, 4, 5, 6};
//检测元素存在
Console.WriteLine(list.Exists(x => x == 6));

搜索元素的索引(通过元素值)

List<int> list = new List<int>() { 1, 2, 3, 3, 2, 1 };
//搜索元素的索引(通过元素值)
Console.WriteLine(list.IndexOf(2));

搜索元素的索引(最后一次出现)(通过元素值)

List<int> list = new List<int>() { 1, 2, 3, 3, 2, 1 };
//搜索元素的索引(最后一次出现)(通过元素值)
Console.WriteLine(list.LastIndexOf(2));

搜索元素的索引(第一个匹配的)(通过元素特征)

List<int> list = new List<int>() { 1, 2, 3, 3, 2, 1 };
//搜索元素的索引(第一个匹配的)(通过元素特征)
Console.WriteLine(list.FindIndex(x => x % 2 == 0));

搜索元素的索引(所有匹配的)(通过元素特征)

List<int> list = new List<int>() { 1, 2, 3, 3, 2, 1 };
//搜索元素的索引(所有匹配的)(通过元素特征)
List<int> result = list.FindAll(x => x % 2 == 0);

搜索元素的索引(最后一次出现)(通过元素特征)

List<int> list = new List<int>() { 1, 2, 3, 3, 2, 1 };
//搜索元素的索引(最后一次出现)(通过元素特征)
Console.WriteLine(list.FindLastIndex(x => x % 2 == 0));

搜索元素的值(通过元素特征)

List<int> list = new List<int>() { 1, 2, 3, 3, 2, 1 };
//搜索元素的值(通过元素特征)
Console.WriteLine(list.Find(x => x % 2 != 0));

搜索元素的值(最后一次出现)(通过元素特征)

List<int> list = new List<int>() { 1, 2, 3, 3, 2, 1 };
//搜索元素的值(最后一次出现)(通过元素特征)
Console.WriteLine(list.FindLast(x => x % 2 != 0));

列表排序

列表中的元素如果实现了IComparer接口,就可以直接调用Sort()方法排序

using System;
using System.Collections.Generic;

namespace Test
{
    class Car:IComparable<Car>
    {
        public decimal Price { get; set; }

        public Car(decimal price)
        {
            this.Price = price;
        }
        public int CompareTo(Car other)
        {
            if(this.Price >= other.Price)
            {
                return 1;
            }
            else
            {
                return -1;
            }
        }
    }
    class TestClass
    {
        public static void Main()
        {
            List<Car> bargage = new List<Car>();
            bargage.Add(new Car(66.66M));
            bargage.Add(new Car(88.88M));
            bargage.Add(new Car(11.11M));
            bargage.Add(new Car(77.77M));
            //排序
            bargage.Sort();

            foreach (var item in bargage)
            {
                Console.WriteLine($"{item.Price}");
            }
            Console.ReadKey();
        }
    }
}

LinkedList

说明

LinkedList表示泛型双向链表(generic doubly linked list)

双向链表示意图
image

LinkedList结构图
image

查询操作

public int Count { get; }                      // Fast
public LinkedListNode<T> First { get; }        // Fast
public LinkedListNode<T> Last { get; }         // Fast
public bool Contains (T value);
public LinkedListNode<T> Find (T value);
public LinkedListNode<T> FindLast (T value);
public void CopyTo (T[] array, int index);
public Enumerator<T> GetEnumerator();

增加元素操作

public void AddFirst(LinkedListNode<T> node);
public LinkedListNode<T> AddFirst (T value);
public void AddLast (LinkedListNode<T> node);
public LinkedListNode<T> AddLast (T value);
public void AddAfter (LinkedListNode<T> node, LinkedListNode<T> newNode);
public LinkedListNode<T> AddAfter (LinkedListNode<T> node, T value);
public void AddBefore (LinkedListNode<T> node, LinkedListNode<T> newNode);
public LinkedListNode<T> AddBefore (LinkedListNode<T> node, T value);

删除元素操作

public void Clear();
public void RemoveFirst();
public void RemoveLast();
public bool Remove (T value);
public void Remove (LinkedListNode<T> node);

实例

新建链表

//直接初始化
LinkedList<int> linkedList1 = new LinkedList<int>();
//使用其他集合初始化
LinkedList<int> linkedList2 = new LinkedList<int>(new List<int> { 1,2,3});

添加到双向链表最后

LinkedList<int> linkedList = new LinkedList<int>();
//添加到双向链表最后
linkedList.AddLast(1);

添加到双向链表最前

LinkedList<int> linkedList = new LinkedList<int>();
//添加到双向链表最前
linkedList.AddFirst(3);

添加元素到双向链表中

LinkedList<int> linkList = new LinkedList<int>();
linkList.AddFirst(666);
linkList.AddLast(888);

foreach (int item in linkList)
{
    Console.WriteLine(item);
}

从双向链表中移除元素

LinkedList<int> linkList = new LinkedList<int>();
linkList.AddFirst(666);
linkList.AddLast(888);

foreach (int item in linkList)
{
    Console.WriteLine(item);
}
//移除指定的值
linkList.Remove(666);
//移除最后一个元素
linkList.RemoveLast();
//输出长度
Console.WriteLine(linkList.Count());//0

获得第一个元素和最后一个元素

LinkedList<int> linkList = new LinkedList<int>();
linkList.AddFirst(666);
linkList.AddLast(888);
linkList.AddAfter(linkList.First, 777);
linkList.AddBefore(linkList.Last, 999);
//获得第一个元素的引用
Console.WriteLine(linkList.First);
//获得第一个元素的值
Console.WriteLine(linkList.First.Value);
//获得最后一个元素的引用
Console.WriteLine(linkList.Last);
//获得最后一个元素的值
Console.WriteLine(linkList.Last.Value);

获得双向链表的元素个数

LinkedList<int> linkedList = new LinkedList<int>();
//获得双向链表的元素个数
Console.WriteLine(linkedList.Count);

查找第一个匹配的节点

LinkedList<int> linkedList = new LinkedList<int>();
//查找第一个匹配的节点
linkedList.Find(3);

查找最后一个匹配的节点

LinkedList<int> linkedList = new LinkedList<int>();
//查找最后一个匹配的节点
linkedList.FindLast(3);

获得第一个节点

LinkedList<int> linkedList = new LinkedList<int>();
//获得第一个节点
Console.WriteLine(linkedList.First.Value);

获得最后一个节点

LinkedList<int> linkedList = new LinkedList<int>();
//获得最后一个节点
Console.WriteLine(linkedList.Last.Value);

检测元素包含

LinkedList<int> linkedList = new LinkedList<int>();
//检测元素包含
linkedList.Contains(3);

移除指定内容的节点

LinkedList<int> linkedList = new LinkedList<int>();
//移除指定内容的节点
linkedList.Remove(3);

移除第一个节点

LinkedList<int> linkedList = new LinkedList<int>();
//移除第一个节点
linkedList.RemoveFirst();

移除最后一个节点

LinkedList<int> linkedList = new LinkedList<int>();
//移除最后一个节点
linkedList.RemoveLast();

插入节点到指定节点之前

LinkedList<int> linkedList = new LinkedList<int>();
//插入节点到指定节点之前
linkedList.AddBefore(linkedList.Last, new LinkedListNode<int>(2));

插入节点到指定节点之后

LinkedList<int> linkedList = new LinkedList<int>();
//插入节点到指定节点之后
linkedList.AddAfter(linkedList.First, new LinkedListNode<int>(2));

清空所有节点

LinkedList<int> linkedList = new LinkedList<int>();
//清空所有节点
linkedList.Clear();

LinkedListNode

说明

表示泛型双向链表的节点

public sealed class LinkedListNode<T>
{
  public LinkedList<T> List { get; }
  public LinkedListNode<T> Next { get; }
  public LinkedListNode<T> Previous { get; }
  public T Value { get; set; }
}

SortList

说明

有序列表

SortedList<TKey,TValue>类型

带排序的列表

底层使用有序数组对(ordered array pair)实现

providing fast retrieval (via a binary-chop search) but poor insertion performance

实例

新建有序列表

SortedList<int, string> sortedList = new SortedList<int, string>();

添加新元素

//添加新元素
SortedList<int, string> sortedList = new SortedList<int, string>();
sortedList.Add(666, "Panda");
sortedList.Add(888, "Dog");

移除元素(通过键)

//移除元素(通过键)
SortedList<int, string> sortedList = new SortedList<int, string>();
sortedList.Remove(666);`

移除元素(通过索引值)

//移除元素(通过索引值)
SortedList<int, string> sortedList = new SortedList<int, string>();
sortedList.RemoveAt(0);
设置/获得有序列表的容量
//设置/获得有序列表的容量
SortedList<int, string> sortedList = new SortedList<int, string>();
Console.WriteLine(sortedList.Capacity);
sortedList.Capacity = 100;

获得有序列表的值集合

//获得有序列表的值集合
SortedList<int, string> sortedList = new SortedList<int, string>();
foreach (string item in sortedList.Values)
{
    Console.WriteLine(item);
}

获得有序列表的键集合

//获得有序列表的键集合
SortedList<int, string> sortedList = new SortedList<int, string>();
foreach (int item in sortedList.Keys)
{
    Console.WriteLine(item);
}

检测是否包含指定键

//检测是否包含指定键
SortedList<int, string> sortedList = new SortedList<int, string>();
bool result1 = sortedList.ContainsKey(666);

检测是否包含指定值

//检测是否包含指定值
SortedList<int, string> sortedList = new SortedList<int, string>();
bool result2 = sortedList.ContainsValue("Panda");

获得指定键的索引

//获得指定键的索引
SortedList<int, string> sortedList = new SortedList<int, string>();
sortedList.IndexOfKey(666);

获得指定值的索引

//获得指定值的索引
SortedList<int, string> sortedList = new SortedList<int, string>();
sortedList.IndexOfValue("Panda");

重设集合大小

//重设集合大小
SortedList<int, string> sortedList = new SortedList<int, string>();
sortedList.TrimExcess();

清空所有元素

//清空所有元素
SortedList<int, string> sortedList = new SortedList<int, string>();
sortedList.Clear();

遍历有序列表

SortedList<int, string> sortedList = new SortedList<int, string>();
foreach (KeyValuePair<int,string> item in sortedList)
{
    Console.WriteLine($"{item.Key}-{item.Value}");
}

DictionaryEntry

DictionaryEntry类型

DictionaryEntry类型结构

public struct DictionaryEntry
{
  public object Key   { get; set; }
  public object Value { get; set; }
}

Dictionary<TKey, TValue>

说明

字典
each element is a key/value pair
注意:
不要对集合元素的枚举顺序做出任何不必要的假设
如果未将集合记录为按特定顺序枚举其元素,则不能保证按任何特定顺序产生元素
Dictionary<TKey, TValue>结构图
image

实例

新建字典

Dictionary<int, string> test = new Dictionary<int, string>();

添加新元素

Dictionary<int, string> test = new Dictionary<int, string>();
test.Add(1, "Panda");

遍历元素

Dictionary<int, string> test = new Dictionary<int, string>();
test.Add(1, "Panda");
foreach (KeyValuePair<int,string> item in test)
{
    Console.WriteLine($"Key:{item.Key} Value:{item.Value}");
}
Dictionary<int, string> dictionary = new Dictionary<int, string>();

获得元素的个数

//获得元素的个数
Dictionary<int, string> dictionary = new Dictionary<int, string>();
Console.WriteLine(dictionary.Count);

检测是否包含键

//检测是否包含键
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.ContainsKey(666);

检测是否包含值

//检测是否包含值
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.ContainsValue("Panda");

移除元素(通过键)

//移除元素(通过键)
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Remove(666);

获得字典的键

//获得字典的键
Dictionary<int, string> dictionary = new Dictionary<int, string>();
foreach (var item in dictionary.Keys)
{
    Console.WriteLine(item);
}

获得字典的值

//获得字典的值
Dictionary<int, string> dictionary = new Dictionary<int, string>();
foreach (var item in dictionary.Values)
{
    Console.WriteLine(item);
}

添加键值对到字典中

//实例化Dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string>();
//添加键值对到字典中
dictionary.Add(666, "Panda");
dictionary[888] = "Dog";
dictionary[999] = "Cat";
dictionary.TryAdd(777, "Monkey");

获得字典中的值

//实例化Dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string>();
//添加键值对到字典中
dictionary.Add(666, "Panda");
dictionary[888] = "Dog";
dictionary[999] = "Cat";
dictionary.TryAdd(777, "Monkey");
//获得字典中的值
dictionary.TryGetValue(888, out string resultVale);
Console.WriteLine(resultVale);
Console.WriteLine(dictionary.GetValueOrDefault(999));

检测键值对存在

//实例化Dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string>();
//添加键值对到字典中
dictionary.Add(666, "Panda");
dictionary[888] = "Dog";
dictionary[999] = "Cat";
dictionary.TryAdd(777, "Monkey");
//获得字典中的值
dictionary.TryGetValue(888, out string resultVale);
Console.WriteLine(resultVale);
Console.WriteLine(dictionary.GetValueOrDefault(999));

//检测键值对存在
Console.WriteLine(dictionary.ContainsKey(888));
Console.WriteLine(dictionary.ContainsValue("Panda"));
Console.WriteLine(dictionary.Contains(new KeyValuePair<int, string>(666,"Panda")));

遍历字典

//实例化Dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string>();
//添加键值对到字典中
dictionary.Add(666, "Panda");
dictionary[888] = "Dog";
dictionary[999] = "Cat";
dictionary.TryAdd(777, "Monkey");
//获得字典中的值
dictionary.TryGetValue(888, out string resultVale);
Console.WriteLine(resultVale);
Console.WriteLine(dictionary.GetValueOrDefault(999));

//检测键值对存在
Console.WriteLine(dictionary.ContainsKey(888));
Console.WriteLine(dictionary.ContainsValue("Panda"));
Console.WriteLine(dictionary.Contains(new KeyValuePair<int, string>(666,"Panda")));

//遍历字典
foreach (KeyValuePair<int,string> item in dictionary)
{
    Console.WriteLine($"Key:{item.Key},Value:{item.Value}");
}

foreach (int item in dictionary.Keys)
{
    Console.WriteLine(item);
}

foreach (string item in dictionary.Values)
{
    Console.WriteLine(item);
}

移除键值对

//实例化Dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string>();
//添加键值对到字典中
dictionary.Add(666, "Panda");
dictionary[888] = "Dog";
dictionary[999] = "Cat";
dictionary.TryAdd(777, "Monkey");

//获得字典中的值
dictionary.TryGetValue(888, out string resultVale);
Console.WriteLine(resultVale);
Console.WriteLine(dictionary.GetValueOrDefault(999));

//检测键值对存在
Console.WriteLine(dictionary.ContainsKey(888));
Console.WriteLine(dictionary.ContainsValue("Panda"));
Console.WriteLine(dictionary.Contains(new KeyValuePair<int, string>(666,"Panda")));

//遍历字典
foreach (KeyValuePair<int,string> item in dictionary)
{
    Console.WriteLine($"Key:{item.Key},Value:{item.Value}");
}

foreach (int item in dictionary.Keys)
{
    Console.WriteLine(item);
}

foreach (string item in dictionary.Values)
{
    Console.WriteLine(item);
}

//移除键值对
dictionary.Remove(666);
string someValue = "Panda";
dictionary.Remove(666,out someValue);

使用多个Key作为Key

本质就是Key是一个Tuple

Dictionary<(int, string), string> dictionary = new Dictionary<(int, string), string>();
dictionary.Add((123, "Panda"), "Panda");
foreach (var item in dictionary)
{
    Console.WriteLine(item.Key.Item1);
    Console.WriteLine(item.Key.Item2);
    Console.WriteLine(item.Value);
}

一个Key对应一个数据集合

本质是Value是一个List/获得其他集合即可

Dictionary<int, List<string>> dictionary = new Dictionary<int, List<string>>();
dictionary.Add(666, new List<string> { "Panda", "Dog" });
foreach (var item in dictionary)
{
    Console.WriteLine(item.Key);
    foreach (var item2 in item.Value)
    {
        Console.WriteLine(item2);
    }
}

多个Key对应一个数据集合

Dictionary<(int, string), (string, int)> dictionary = new Dictionary<(int, string), (string, int)>();
dictionary.Add((666, "Panda"), ("Panda", 666));
foreach (var item in dictionary)
{
    Console.WriteLine(item.Key.Item1);
    Console.WriteLine(item.Key.Item2);
    Console.WriteLine(item.Value.Item1);
    Console.WriteLine(item.Value.Item2);
}

SortedDictionary<TKey,TValue>

SortedDictionary<TKey,TValue>

说明

带排序的字典

底层使用红黑树(red/black tree)实现

SortedDictionary<TKey, TValue> and SortedList结构图

image

实例

OrderedDictionary

说明

有序字典,从.NET 2.0开始引入

混合了Hashtable类型 和 ArrayList类型 的功能

注意:这是非泛型类型,没有对应的泛型类型

所在命名空间

using System.Collections.Specialized;

添加元素

OrderedDictionary orderedDictionary = new OrderedDictionary();
orderedDictionary.Add(666, "Panda");

ListDictionary

说明

use singly linked list to store the underlying data

注意:没有对应的泛型类型

所在命名空间

using System.Collections.Specialized;

HybridDictionary

说明

its efficiency with very small lists (fewer than 10 items)

注意:没有对应的泛型类型

所在命名空间

using System.Collections.Specialized;

所在命名空间

using System.Collections.Specialized;

Stack

说明

Stack表示栈

last-in, first-out (LIFO) data structures

Stack结构图

image

主要操作

public class Stack<T> : IEnumerable<T>, ICollection, IEnumerable
{
  public Stack();
  public Stack (IEnumerable<T> collection);   // Copies existing elements
  public Stack (int capacity);                // Lessens auto-resizing
  public void Clear();
  public bool Contains (T item);
  public void CopyTo (T[] array, int arrayIndex);
  public int Count { get; }
  public Enumerator<T> GetEnumerator();       // To support foreach
  public T Peek();
  public T Pop();
  public void Push (T item);
  public T[] ToArray();
  public void TrimExcess();
}

实例

初始化栈

//初始化栈
Stack<int> stack1 = new Stack<int>();
//指定容量
Stack<int> stack2 = new Stack<int>(100);
//使用其他集合进行初始化
Stack<int> stack3 = new Stack<int>(new List<int> { 1, 2, 3 });

进栈

//进栈
stack1.Push(1);

出栈

//出栈
Console.WriteLine(stack1.Pop());

获得栈中元素个数

//获得栈中元素个数
Console.WriteLine(stack1.Count);

获得栈顶元素,但不删除

//获得栈顶元素,但不删除
Console.WriteLine(stack1.Peek());

检测是否包含指定元素

//检测是否包含指定元素
Console.WriteLine(stack1.Contains(2));

栈主要操作

Stack<string> stack = new Stack<string>();
//添加元素到栈中
stack.Push("Panda666");
stack.Push("Dog666");
stack.Push("Dog666");
//获得栈的长度
Console.WriteLine(stack.Count());
//获得栈顶元素
Console.WriteLine(stack.Peek());
//出栈
Console.WriteLine(stack.Pop());
//检测是否包含元素值
Console.WriteLine(stack.Contains("Dog666")?"包含":"不包含");
//获得栈顶元素
Console.WriteLine(stack.Peek());
//转为数组
string[] result1 = stack.ToArray();
//转为List<T>
List<string> result2 = stack.ToList();

Queue

说明

Queue代表队列
first-in, first-out (FIFO) data structures
members cannot be accessed directly by index
Queue结构图

image

常用操作

public class Queue<T> : IEnumerable<T>, ICollection, IEnumerable
{
  public Queue();
  public Queue (IEnumerable<T> collection);   // Copies existing elements
  public Queue (int capacity);                // To lessen auto-resizing
  public void Clear();
  public bool Contains (T item);
  public void CopyTo (T[] array, int arrayIndex);
  public int Count { get; }
  public T Dequeue();   //进队
  public void Enqueue (T item); //出队
  public Enumerator<T> GetEnumerator();       // To support foreach
  public T Peek();      //获得队顶元素
  public T[] ToArray(); //转为数组
  public void TrimExcess();
}

实例

新建队列

//直接新建
Queue<int> queue1 = new Queue<int>();
//设置容量初始化
Queue<int> queue2 = new Queue<int>(100);
//使用其他集合初始化
Queue<int> queue = new Queue<int>(new List<int> { 1, 2, 3 });

获得队列中元素个数

Queue<int> queue = new Queue<int>();
//进队
queue.Enqueue(1);
//获得队列的元素个数
Console.WriteLine(queue.Count);

进队

Queue<int> queue = new Queue<int>();
//进队
queue.Enqueue(1);

出队

Queue<int> queue = new Queue<int>();
//进队
queue.Enqueue(1);
//出队
Console.WriteLine(queue.Dequeue());

获得队顶元素

Queue<int> queue = new Queue<int>();
//进队
queue.Enqueue(1);
//获得队顶元素,但不出队
Console.WriteLine(queue.Peek());

重设队列容量

Queue<int> queue = new Queue<int>();
//重设队列容量
queue.TrimExcess();

队列基本操作

Queue<string> queue = new Queue<string>();
//进队列
queue.Enqueue("Panda");
queue.Enqueue("Dog");
queue.Enqueue("Cat");
//获得个数
Console.WriteLine(queue.Count());
//检测元素存在
Console.WriteLine(queue.Contains("Dog") ? "包含" : "不包含");
//获得队列顶部元素
Console.WriteLine(queue.Peek());
//出队列
Console.WriteLine(queue.Dequeue());

//转为数组
string[] result = queue.ToArray();
foreach (string item in result)
{
    Console.WriteLine(item);
}

//转为List<T>
List<string> result2 = queue.ToList();
foreach (string item in result2)
{
    Console.WriteLine(item);
}

HashSet

说明

不重复元素的无序列表

HashSet is implemented with a hashtable

集合操作

public void UnionWith           (IEnumerable<T> other);   // Adds
public void IntersectWith       (IEnumerable<T> other);   // Removes
public void ExceptWith          (IEnumerable<T> other);   // Removes
public void SymmetricExceptWith (IEnumerable<T> other);   // Removes
public bool IsSubsetOf         (IEnumerable<T> other);
public bool IsProperSubsetOf   (IEnumerable<T> other);
public bool IsSupersetOf       (IEnumerable<T> other);
public bool IsProperSupersetOf (IEnumerable<T> other);
public bool Overlaps           (IEnumerable<T> other);
public bool SetEquals          (IEnumerable<T> other);

实例

基本操作

HashSet<string> hashset = new HashSet<string>();
hashset.Add("Panda666");
hashset.Add("Dog666");
hashset.Remove("Cat666");

//倒序处理
var result1 = hashset.Reverse();
foreach (string item in result1)
{
    Console.WriteLine(item);
}

SortSet

说明

不重复元素的有序列表

SortedSet is implemented with a red/black tree

实例

添加元素

//添加元素
HashSet<int> hashSet = new HashSet<int>();
hashSet.Add(1);

移除元素

//移除元素
HashSet<int> hashSet = new HashSet<int>();
hashSet.Remove(1);

获得元素的个数

//获得元素的个数
HashSet<int> hashSet = new HashSet<int>();
int count = hashSet.Count;

清空所有元素

//清空所有元素
HashSet<int> hashSet = new HashSet<int>();
hashSet.Clear();

检测包含元素

//检测包含元素
HashSet<int> hashSet = new HashSet<int>();
hashSet.Contains(1);

重设集合的大小

//重设集合的大小
HashSet<int> hashSet = new HashSet<int>();
hashSet.TrimExcess();

基本操作

SortedSet<int> sortedSet = new SortedSet<int>();
sortedSet.Add(1);
sortedSet.Add(2);
sortedSet.Add(3);

Console.WriteLine(sortedSet.Max());
Console.WriteLine(sortedSet.Min());
Console.WriteLine(sortedSet.Sum());

BitArray

说明

存储位的集合

命名空间:System.Collecions

dynamically sized collection of compacted bool values

only one bit for each value

实例

初始化BitArray

//初始化,设置位数
BitArray bitArray0 = new BitArray(10);
//初始化,设置位数和默认值
BitArray bitArray1 = new BitArray(10, true);
//初始化,用另一个位集合初始化
BitArray bitArray2 = new BitArray(bitArray1);
//初始化,用布尔数组初始化
BitArray bitArray3 = new BitArray(new bool[] { true, false });
//初始化,用字节数组初始化
BitArray bitArray4 = new BitArray(new byte[] { 1, 2, 3, 4 });
//初始化,用整型数组初始化
BitArray bitArray5 = new BitArray(new int[] { 1, 2, 3, 4 });

获得集合中元素个数

BitArray bitArray0 = new BitArray(10);
//获得集合中元素个数
Console.WriteLine(bitArray0.Count);

使用索引访问元素

BitArray bitArray0 = new BitArray(10);
//使用索引访问元素
bitArray0[0] = true;
Console.WriteLine(bitArray0[0]);

使用set设置值

BitArray bitArray0 = new BitArray(10);
//使用set设置值
bitArray0.Set(1, true);

使用get访问值

BitArray bitArray0 = new BitArray(10);
//使用get访问值
Console.WriteLine(bitArray0.Get(1));

设置所有参数

BitArray bitArray0 = new BitArray(10);
//设置所有参数
bitArray0.SetAll(true);

所有位取反

BitArray bitArray0 = new BitArray(10);
//所有位取反
bitArray0.Not();

与其他位集合执行与运算

BitArray bitArray0 = new BitArray(10);
BitArray bitArray1 = new BitArray(10, true);
//与其他位集合执行与运算
bitArray0.And(bitArray1);

与其他位集合执行或运算

BitArray bitArray0 = new BitArray(10);
BitArray bitArray1 = new BitArray(10, true);
//与其他位集合执行或运算
bitArray0.Or(bitArray1);

与其他位集合执行异或运算

BitArray bitArray0 = new BitArray(10);
BitArray bitArray1 = new BitArray(10, true);
//与其他位集合执行异或运算
bitArray0.Xor(bitArray1);

设置位集合的长度

BitArray bitArray0 = new BitArray(10);
//设置位集合的长度
bitArray0.Length = 5;

BitVector32

说明

存储位的集合结构,最多只能有32个位

该集合是一个值类型,效率比BitArray高,但位数有限制

命名空间:System.Collecions.Specialized;

实例

初始化BitVector32

//初始化
BitVector32 bitVector32_1 = new BitVector32();
//初始化,使用另一个BitVector初始化
BitVector32 bitVector32_2 = new BitVector32(bitVector32_1);
//初始化,使用整型值初始化
BitVector32 bitVector32_3 = new BitVector32(10);

获得内容(整型值)

//获得内容(整型值)
BitVector32 bitVector32_1 = new BitVector32();
Console.WriteLine(bitVector32_1.Data);

获得内容(二进制字符串)

//获得内容(二进制字符串)
BitVector32 bitVector32_1 = new BitVector32();
Console.WriteLine(bitVector32_1.ToString());

设置位

//设置位
BitVector32 bitVector32_1 = new BitVector32();
bitVector32_1[0] = true;

读取位

//读取位
BitVector32 bitVector32_1 = new BitVector32();
Console.WriteLine(bitVector32_1[0]);

ObservableCollection

说明

命名空间:System.Collections.ObjectModel;

ObservableCollection类派生自Collection

实例

初始化ObservableCollection

//直接初始化
ObservableCollection<string> c1 = new ObservableCollection<string>();
//使用其他集合初始化
ObservableCollection<string> c1 = new ObservableCollection<string>();
ObservableCollection<string> c2 = new ObservableCollection<string>(c1);
//使用list初始化
List<string> list = new List<string> { "Panda", "Dog" };
ObservableCollection<string> c3 = new ObservableCollection<string>(list);

添加元素

ObservableCollection<string> c1 = new ObservableCollection<string>();
//添加元素
c1.Add("Panda666.com");

删除元素(指定值)

ObservableCollection<string> c1 = new ObservableCollection<string>();
//删除元素(指定值)
c1.Remove("Panda666.com");

删除元素(指定索引)

ObservableCollection<string> c1 = new ObservableCollection<string>();
//删除元素(指定索引)
c1.RemoveAt(0);

清空元素

ObservableCollection<string> c1 = new ObservableCollection<string>();
//清空元素
c1.Clear();

获得元素的个数

ObservableCollection<string> c1 = new ObservableCollection<string>();
//获得元素的个数
Console.WriteLine(c1.Count);

检测包含元素值

ObservableCollection<string> c1 = new ObservableCollection<string>();
//检测包含元素值
Console.WriteLine(c1.Contains("Panda666.com"));

插入元素

ObservableCollection<string> c1 = new ObservableCollection<string>();
//插入元素
c1.Insert(1, "panda666");

移动元素

ObservableCollection<string> c1 = new ObservableCollection<string>();
//移动元素
c1.Move(0, 1);

查找指定值

ObservableCollection<string> c1 = new ObservableCollection<string>();
//查找指定值
Console.WriteLine(c1.IndexOf("Panda666"));

监听集合变化事件

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections.ObjectModel;

namespace Test
{
    class TestClass
    {
        public static void Main()
        {
            ObservableCollection<string> c1 = new ObservableCollection<string>();

            //添加事件:集合改变触发
            c1.CollectionChanged += NotifyChanged;

            //添加元素
            c1.Add("Panda666.com");
            c1.Add("Panda666.com");

            Console.ReadKey();
        }

        /// <summary>
        /// 事件处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static void NotifyChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch(e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    Console.WriteLine("Add Item");
                    break;
                case NotifyCollectionChangedAction.Remove:
                    Console.WriteLine("Remove Item");
                    break;
                case NotifyCollectionChangedAction.Replace:
                    Console.WriteLine("Replace Item");
                    break;
                case NotifyCollectionChangedAction.Reset:
                    Console.WriteLine("Reset ");
                    break;
                case NotifyCollectionChangedAction.Move:
                    Console.WriteLine("Move Item");
                    break;
            }
        }
    }
}

ReadOnlyCollection

ReadOnlyCollection is a wrapper, or proxy, that provides a read-only view of a collection

只读字典接口,常用于对外暴露字典,只用于读取使用

ConcurrentBag

说明

实例

ConcurrentDictionary

说明

实例

ConcurrentQueue

说明

实例

ConcurrentStack

说明

实例

ConcurrentExclusiveSchedulerPair

说明

实例

ImmutableArray

说明

ImmutableArray的读取性能非常强,但添加元素也是非常慢

实例

实例:创建不可变Array

ImmutableArray<int> array = ImmutableArray.Create<int> (1, 2, 3);

实例:从可变类型转为不可变类型

var list = new[] { 1, 2, 3 }.ToImmutableList();

实例:使用会引起变化的方法会返回新的集合

var oldList = ImmutableList.Create<int> (1, 2, 3);
ImmutableList<int> newList = oldList.Add (4);
var anotherList = oldList.AddRange (new[] { 4, 5, 6 });
Console.WriteLine (oldList.Count); // 3 (unaltered)
Console.WriteLine (newList.Count); // 4

实例:创建Builder来实例化

ImmutableArray<int>.Builder builder = ImmutableArray.CreateBuilder<int>();
builder.Add (1);
builder.Add (2);
builder.Add (3);
builder.RemoveAt (0);
ImmutableArray<int> myImmutable = builder.ToImmutable();

ImmutableStack

ImmutableQueue

说明

实例

ImmutableDictionary

说明

实例

ImmutableSortedDictionary<K,V>

ImmutableSortedSet

ImmutableHashSet

ImmutableList

说明

不可变集合

ImmutableList的读取性能非常慢,添加元素的性能也很低

实例

实例:测试集合的不可变性

using System;
using System.Collections.Generic;
using System.Collections.Immutable;

namespace ConsoleApp6
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> cities = new List<string>();
            //immutableCities为不可变集合,添加元素不会影响
            var immutableCities = cities.ToImmutableList();
            //添加元素后返回新的集合,原集合不会改变
            var newList = immutableCities.Add("Rio");
            //原集合
            foreach (string city in immutableCities)
            {
                Console.Write($" {city}");
            }
            Console.WriteLine();

            //新集合
            foreach (string city in newList)
            {
                Console.Write($" {city}");
            }

            //wait
            Console.ReadKey();
        }
    }
}

BlockingCollection多线程写入和读取

using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            BlockingCollection<int> bc = new BlockingCollection<int>();
            
            //写入数据任务1
            Task writeDataTask1 = Task.Run(() => {
                for (int i = 0; i < 100; i++)
                {
                    if(bc.TryAdd(i))
                    {
                        Console.WriteLine($"写入数据任务1,成功写入:{i}");
                    }
                }
            });

            //写入数据任务2
            Task writeDataTask2 = Task.Run(() => {
                for (int i = 100; i < 200; i++)
                {
                    if (bc.TryAdd(i))
                    {
                        Console.WriteLine($"写入数据任务2,成功写入:{i}");
                    }
                }
            });

            //等待写入任务完成
            Task.WaitAll(new Task[] { writeDataTask1, writeDataTask2 });

            //标记写入任务完成
            bc.CompleteAdding();

            //读取任务1
            Task readDataTask1 = Task.Run(() => {
                while(!bc.IsCompleted)
                {
                    if (bc.TryTake(out int data))
                    {
                        Console.WriteLine($"读取任务1.成功读取:{data}");
                    }
                }
            });

            //读取任务2
            Task readDataTask2 = Task.Run(() => {
                while (!bc.IsCompleted)
                {
                    if (bc.TryTake(out int data))
                    {
                        Console.WriteLine($"读取任务2.成功读取:{data}");
                    }
                }
            });

            //释放集合
            bc.Dispose();

            //wait
            Console.ReadKey();
        }
    }
}

ConcurrentStack多线程写入和读取

using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建集合
            ConcurrentStack<int> stack = new ConcurrentStack<int>();

            //写入任务1
            Task writeDataTask1 = Task.Run(() =>
            {
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine($"写入任务1:正在写入{i}");
                    stack.Push(i);
                }
            });

            //写入任务2
            Task writeDataTask2 = Task.Run(() =>
            {
                for (int i = 100; i < 200; i++)
                {
                    Console.WriteLine($"写入任务2:正在写入{i}");
                    stack.Push(i);
                }
            });

            //等待写入任务完成
            Task.WaitAll(new Task[] { writeDataTask1, writeDataTask2 });

            //读取任务1
            Task readDataTask1 = Task.Run(() => {
                //先检查是否为空
                while(stack.Count > 0)
                {
                    if(stack.TryPop(out int data))
                    {
                        Console.WriteLine($"读取任务1-数据:{data}");
                    }
                }
            });

            //读取任务2
            Task readDataTask2 = Task.Run(() => {
                //先检查是否为空
                while (stack.Count>0)
                {
                    if (stack.TryPop(out int data))
                    {
                        Console.WriteLine($"读取任务2-数据:{data}");
                    }
                }
            });

            //wait
            Console.ReadKey();
        }
    }
}

SortedDictionary自定义排序规则

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    /// <summary>
    /// 自定义有序字典比较器
    /// </summary>
    public class SortedDictionaryCustomComparear : IComparer<int>
    {
        public int Compare(int x, int y)
        {
            if(x >= y)
            {
                return 1;
            }
            else
            {
                return -1;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //使用自定义的字典初始化有序字典
            SortedDictionary<int, string> sd = new SortedDictionary<int, string>(new SortedDictionaryCustomComparear());

            //增加元素
            sd.Add(666, "Panda");
            sd.Add(555, "Cat");
            sd.Add(333, "Dog");
            sd.Add(888, "Monkey");

            //遍历输出
            foreach (var item in sd)
            {
                Console.WriteLine($"{item.Key}-{item.Value}");
            }
            //333-Dog
            //555-Cat
            //666-Panda
            //888-Monkey

            //wait
            Console.ReadKey();
        }
    }
}

参考链接

https://www.cnblogs.com/jesse2013/p/CollectionsInCSharp.html

posted @ 2022-09-30 08:37  重庆熊猫  阅读(542)  评论(0编辑  收藏  举报