【C#教程15/16】: 数据容器(collection)

一、C# 数据容器(collection)

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

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

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

        对容器模式的解释

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

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

二、C# 列表(List)

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

Program.cs

var langs = new List<string>();

langs.Add("Java");
langs.Add("C#");
langs.Add("C");
langs.Add("C++");
langs.Add("Ruby");
langs.Add("Javascript");

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

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

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

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

langs.Insert(4, "Haskell");

langs.Sort();

foreach (string lang in langs)
{
    Console.WriteLine(lang);
}

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

        using System.Collections.Generic;

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

        var langs = new List<string>();

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

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

using System.Collections;

var data = new ArrayList();

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

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

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<int>() { 1, 2, 3, 4, 5, 6, 7 };

int sum = vals.Sum();
Console.WriteLine(sum);

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

$ dotnet run
28

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

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

Program.cs

var sorted = new SortedList<string, int>();

sorted.Add("coins", 3);
sorted.Add("books", 41);
sorted.Add("spoons", 5);

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

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

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

var sorted = new SortedList<string, int>();

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

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<int>();

nums.AddLast(23);
nums.AddLast(34);
nums.AddLast(33);
nums.AddLast(11);
nums.AddLast(6);
nums.AddFirst(9);
nums.AddFirst(7);

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

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

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

var nums = new LinkedList<int>();

        这是一个整数 LinkedList。

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

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

LinkedListNode<int> 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<string, string>();

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<string>(domains.Keys);

foreach (string key in keys)
{
    Console.WriteLine("{0}", key);
}

Console.WriteLine("Values of the dictionary:");

var vals = new List<string>(domains.Values);

foreach (string val in vals)
{
    Console.WriteLine("{0}", val);
}

Console.WriteLine("Keys and values of the dictionary:");

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

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

var domains = new Dictionary<string, string>();

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

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<string>(domains.Keys);

foreach(string key in keys)
{
    Console.WriteLine("{0}", key);
}  

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

var vals = new List<string>(domains.Values);

foreach(string val in vals)
{
    Console.WriteLine("{0}", val);
}

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

foreach(KeyValuePair<string, string> 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

var msgs = new Queue<string>();
msgs.Enqueue("Message 1");
msgs.Enqueue("Message 2");
msgs.Enqueue("Message 3");
msgs.Enqueue("Message 4");
msgs.Enqueue("Message 5");
Console.WriteLine(msgs.Dequeue());
Console.WriteLine(msgs.Peek());
Console.WriteLine(msgs.Peek());
Console.WriteLine();
foreach (string msg in msgs)
{
    Console.WriteLine(msg);
}

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

var msgs = new Queue<string>();

        创建了一个字符串队列。

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<int>();

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<int>();

        创建堆栈数据结构。

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无水先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值