• C#教程15: 数据容器(collection)


    一、C# 数据容器(collection)

            在本章中,我们处理 C# 数据容器。 .NET 框架为数据存储和检索提供了专门的类。在前面的一章中,我们已经描述了数组。集合是对数组的增强。

            C# 中有三种不同的集合类型:

    • standard 标准
    • generic 通用的
    • concurrent 同时

            对容器模式的解释

    • 标准集合位于 System.Collections 下。它们不会将元素存储为特定类型的对象,而是存储为 Object 类型的对象。标准集合包括 ArrayList、Hashtable、Queue 和 Stack。
    • 通用集合位于 System.Collections.Generic 下。通用集合更灵活,是处理数据的首选方式。泛型增强了代码重用、类型安全和性能。通用集合包括 Dictionary、List、Queue、SortedList 和 Stack
    • 并发集合包括 BlockingCollection、ConcurrentDictionary、ConcurrentQueue 和 ConcurrentStack

            泛型编程是一种计算机编程风格,其中算法是根据待指定的类型编写的,然后在需要时为作为参数提供的特定类型实例化。这种方法由 Ada 于 1983 年首创,允许编写常见的函数或类型,这些函数或类型仅在使用时所操作的类型集有所不同,从而减少了重复。

    二、C# 列表(List)

            List 是可以通过索引访问的对象的强类型列表。它可以在 System.Collections.Generic 命名空间下找到。命名空间会自动包含在隐式 usings 中。

    Program.cs

    1. var langs = new List<string>();
    2. langs.Add("Java");
    3. langs.Add("C#");
    4. langs.Add("C");
    5. langs.Add("C++");
    6. langs.Add("Ruby");
    7. langs.Add("Javascript");
    8. Console.WriteLine(langs.Contains("C#"));
    9. Console.WriteLine(langs[1]);
    10. Console.WriteLine(langs[2]);
    11. langs.Remove("C#");
    12. langs.Remove("C");
    13. Console.WriteLine(langs.Contains("C#"));
    14. langs.Insert(4, "Haskell");
    15. langs.Sort();
    16. foreach (string lang in langs)
    17. {
    18. Console.WriteLine(lang);
    19. }

            在前面的示例中,我们使用 List 集合。

            using System.Collections.Generic;
    

            List 集合位于 System.Collections.Generic 命名空间中。

            var langs = new List();
    

            创建一个通用动态数组。我们指定使用 <> 字符内指定类型的字符串。

    langs.Add("Java");
    langs.Add("C#");
    langs.Add("C");
    ...
    

            我们使用 Add 方法将元素添加到列表中。

    Console.WriteLine(langs.Contains("C#"));
    

            我们使用 Contains 方法检查列表是否包含特定字符串。

    Console.WriteLine(langs[1]);
    Console.WriteLine(langs[2]);
    

            我们使用索引表示法访问 List 的第二个和第三个元素。

    langs.Remove("C#");
    langs.Remove("C");
    

            我们从列表中删除两个字符串。

    langs.Insert(4, "Haskell");
    

            我们在特定位置插入一个字符串。

    langs.Sort();
    

            我们使用排序方法对元素进行排序。

    $ dotnet run
    True
    C#
    C
    False
    C++
    Haskell
    Java
    Javascript
    Ruby 

    三、C# 数组列表(ArrayList)

            ArrayList 是来自标准 System.Collections 命名空间的集合。它是一个动态数组。它提供对其元素的随机访问。随着数据的添加,ArrayList 会自动扩展。与数组不同,ArrayList 可以保存多种数据类型的数据。 ArrayList 中的元素通过整数索引访问。索引从零开始。 ArrayList 末尾的元素索引以及插入和删除需要恒定的时间。在动态数组中间插入或删除元素的成本更高。它需要线性时间。

    Program.cs

    1. using System.Collections;
    2. var data = new ArrayList();
    3. data.Add("Visual Basic");
    4. data.Add(344);
    5. data.Add(55);
    6. data.Add(new Empty());
    7. data.Remove(55);
    8. foreach (object el in data)
    9. {
    10. Console.WriteLine(el);
    11. }
    12. class Empty {}

            在上面的示例中,我们创建了一个 ArrayList 集合。我们在其中添加了一些元素。它们具有各种数据类型、字符串、整数和类对象。

    using System.Collections;
    

            为了使用 ArrayList 集合,我们需要使用 System.Collections 命名空间。

    var data = new ArrayList();
    

            创建了一个 ArrayList 集合。

    data.Add("Visual Basic");
    data.Add(344);
    data.Add(55);
    data.Add(new Empty());
    data.Remove(55);
    

            我们使用 Add 方法将四个元素添加到数组中。

    data.Remove(55);
    

            我们使用 Remove 方法删除一个元素。

    foreach(object el in data)
    {
        Console.WriteLine(el);
    }
    

            我们遍历数组并将其元素打印到控制台。

    $ dotnet run
    Visual Basic
    344
    Emptys


    四、​​​​​C#数据容器的初始化( collection initializers)

            集合初始化器允许在对象创建期间在 {} 括号内指定集合的​​元素。

    Program.cs

    var vals = new List() { 1, 2, 3, 4, 5, 6, 7 };
    
    int sum = vals.Sum();
    Console.WriteLine(sum);
    

            该示例创建一个列表并打印其总和。列表的元素在集合初始值设定项中指定。

    $ dotnet run
    28
    

    五、C#带排序的列表( SortedList)

       SortedList 表示一个数集,包含键名和键值对, key/value对,可以依之排序。

    Program.cs

    1. var sorted = new SortedList<string, int>();
    2. sorted.Add("coins", 3);
    3. sorted.Add("books", 41);
    4. sorted.Add("spoons", 5);
    5. if (sorted.ContainsKey("books"))
    6. {
    7. Console.WriteLine("There are books in the list");
    8. }
    9. foreach (var pair in sorted)
    10. {
    11. Console.WriteLine(pair);
    12. }

            该示例使用排序列表来组织项目。

    var sorted = new SortedList();
    

            排序列表具有字符串键和整数值。

    if (sorted.ContainsKey("books"))
    {
        Console.WriteLine("There are books in the list");
    }
    

            我们使用 ContainsKey 检查集合中是否有书籍。

    foreach (var pair in sorted)
    {
        Console.WriteLine(pair);
    }
    

            使用 foreach 循环,我们遍历集合并打印它的对。

    $ dotnet run
    There are books in the list
    [books, 41]
    [coins, 3]
    [spoons, 5]

    六、C#链接列表LinkedList

            LinkedList 是 C# 中的通用双向链表。 LinkedList 只允许顺序访问。 LinkedList 允许固定时间的插入或删除,但只能顺序访问元素。因为链表需要额外的存储空间来存储引用,所以它们对于诸如字符之类的小数据项的列表是不切实际的。

            与动态数组不同,可以将任意数量的项目添加到链表中(当然受内存限制),而无需重新分配,这是一项昂贵的操作。

    Program.cs

    var nums = new LinkedList();
    
    nums.AddLast(23);
    nums.AddLast(34);
    nums.AddLast(33);
    nums.AddLast(11);
    nums.AddLast(6);
    nums.AddFirst(9);
    nums.AddFirst(7);
    
    LinkedListNode node = nums.Find(6);
    nums.AddBefore(node, 5);
    
    foreach (int num in nums)
    {
        Console.WriteLine(num);
    }
    

            这是一个带有一些方法的 LinkedList 示例。

    var nums = new LinkedList();
    

            这是一个整数 LinkedList。

    nums.AddLast(23);
    ...
    nums.AddFirst(7);
    

            我们使用 AddLast 和 AddFirst 方法填充链接列表。

    LinkedListNode node = nums.Find(6);
    nums.AddBefore(node, 5);
    

            LinkedList 由节点组成。我们找到一个特定的节点并在它之前添加一个元素。

    foreach(int num in nums)
    {
        Console.WriteLine(num);
    }
    

    ·        我们正在将所有元素打印到控制台。

    $ dotnet run
    7
    9
    23
    34
    33
    11

    七、C# 字典(Dictionary)

            字典也称为关联数组,是唯一键的集合和值的集合,其中每个键与一个值相关联。检索和添加值非常快。字典占用更多内存,因为每个值还有一个键。

    Program.cs

    var domains = new Dictionary();
    
    domains.Add("de", "Germany");
    domains.Add("sk", "Slovakia");
    domains.Add("us", "United States");
    domains.Add("ru", "Russia");
    domains.Add("hu", "Hungary");
    domains.Add("pl", "Poland");
    
    Console.WriteLine(domains["sk"]);
    Console.WriteLine(domains["de"]);
    
    Console.WriteLine("Dictionary has {0} items", domains.Count);
    
    Console.WriteLine("Keys of the dictionary:");
    
    var keys = new List(domains.Keys);
    
    foreach (string key in keys)
    {
        Console.WriteLine("{0}", key);
    }
    
    Console.WriteLine("Values of the dictionary:");
    
    var vals = new List(domains.Values);
    
    foreach (string val in vals)
    {
        Console.WriteLine("{0}", val);
    }
    
    Console.WriteLine("Keys and values of the dictionary:");
    
    foreach (KeyValuePair kvp in domains)
    {
        Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
    }
    

            我们有一个字典,我们将域名映射到他们的国家名称。

    var domains = new Dictionary();
    

            我们创建一个带有字符串键和值的字典。

    domains.Add("de", "Germany");
    domains.Add("sk", "Slovakia");
    domains.Add("us", "United States");
    ...
    

            我们将一些数据添加到字典中。第一个字符串是键。二是价值。

    Console.WriteLine(domains["sk"]);
    Console.WriteLine(domains["de"]);
    

            在这里,我们通过它们的键检索两个值。

    Console.WriteLine("Dictionary has {0} items", domains.Count);
    

            我们通过引用 Count 属性打印项目数。

    var keys = new List(domains.Keys);
    
    foreach(string key in keys)
    {
        Console.WriteLine("{0}", key);
    }  
    

            这些行从字典中检索所有键。

    var vals = new List(domains.Values);
    
    foreach(string val in vals)
    {
        Console.WriteLine("{0}", val);
    }
    

            这些行从字典中检索所有值。

    foreach(KeyValuePair kvp in domains)
    {
        Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
    }
    

            最后,我们打印字典的键和值。

    $ dotnet run
    Slovakia
    Germany
    Dictionary has 6 items
    Keys of the dictionary:
    de
    sk
    us
    ru
    hu
    pl
    Values of the dictionary:
    Germany
    Slovakia
    United States
    Russia
    Hungary
    Poland
    Keys and values of the dictionary:
    Key = de, Value = Germany
    Key = sk, Value = Slovakia
    Key = us, Value = United States
    Key = ru, Value = Russia
    Key = hu, Value = Hungary
    Key = pl, Value = Poland

    八、C#队列( Queues)

            队列是一种先进先出 (FIFO) 数据结构。添加到队列的第一个元素将是第一个被删除的元素。队列可用于在消息出现时处理消息或在客户到来时为其提供服务。第一个来的顾客应该首先得到服务。

    Program.cs

    1. var msgs = new Queue<string>();
    2. msgs.Enqueue("Message 1");
    3. msgs.Enqueue("Message 2");
    4. msgs.Enqueue("Message 3");
    5. msgs.Enqueue("Message 4");
    6. msgs.Enqueue("Message 5");
    7. Console.WriteLine(msgs.Dequeue());
    8. Console.WriteLine(msgs.Peek());
    9. Console.WriteLine(msgs.Peek());
    10. Console.WriteLine();
    11. foreach (string msg in msgs)
    12. {
    13.     Console.WriteLine(msg);
    14. }

            在我们的示例中,我们有一个包含消息的队列。

    var msgs = new Queue();
    

            创建了一个字符串队列。

    msgs.Enqueue("Message 1");
    msgs.Enqueue("Message 2");
    ...
    

            Enqueue 将消息添加到队列的末尾。

    Console.WriteLine(msgs.Dequeue());

            Dequeue 方法移除并返回队列开头的项目。

    Console.WriteLine(msgs.Peek());

            Peek 方法从队列中返回下一个项目,但不会将其从集合中移除。

    $ dotnet run
    Message 1
    Message 2
    Message 2
    
    Message 2
    Message 3
    Message 4
    Message 5
    

            Dequeue 方法从集合中删除“消息 1”。 Peek 方法不会。 “消息 2”保留在集合中。

    九、C#栈 Stacks

            堆栈是一种后进先出 (LIFO) 数据结构。添加到队列中的最后一个元素将是第一个被删除的元素。 C 语言使用堆栈将本地数据存储在函数中。实现计算器时也使用堆栈。

    Program.cs

    var myStack = new Stack();
    
    myStack.Push(1);
    myStack.Push(4);
    myStack.Push(3);
    myStack.Push(6);
    myStack.Push(4);
    
    Console.WriteLine(myStack.Pop());
    Console.WriteLine(myStack.Peek());
    Console.WriteLine(myStack.Peek());
    
    Console.WriteLine();
    
    foreach (int item in myStack)
    {
        Console.WriteLine(item);
    }
    

            上面有一个简单的堆栈示例。

    var myStack = new Stack();
    

            创建堆栈数据结构。

    myStack.Push(1);
    myStack.Push(4);
    ...
    

            Push 方法在堆栈顶部添加一个项目。

    Console.WriteLine(stc.Pop());
    

            Pop 方法从堆栈顶部移除并返回项目。

    Console.WriteLine(myStack.Peek());
    

            Peek 方法从堆栈顶部返回项目。它不会删除它。

    $ dotnet run
    4
    6
    6
    
    6
    3
    4
    1
  • 相关阅读:
    SPARQL基础入门练习
    [Java SE] 经典问题:超出Java Long型(8字节/64位)的二进制比特流数据如何进行大数的数值计算?
    ROS-读取/map话题转化为pgm文件(代码版map_server)
    时域分析
    Android MediaMetadataRetriever setDataSource failed: status = 0xFFFFFFEA
    k8s存储卷
    【智能家居-大模型】行业专题报告:ChatGPT等大模型催化智能家居行业发展
    【杂项笔记】Linux使用相关指令(持续更新)
    C++行为型模式-中介者模式
    Ribbon和LoadBalancer自定义负载均衡算法及配置
  • 原文地址:https://blog.csdn.net/gongdiwudu/article/details/123445967