集合
IEnumerable<T>:
-
功能:
IEnumerable<T>
是用于提供对集合进行简单迭代的接口。它定义了一个单一的方法GetEnumerator()
,通过该方法可以获取一个实现了IEnumerator<T>
接口的迭代器,用于按顺序访问集合中的元素。 -
特性:
IEnumerable<T>
是最基本的集合接口,提供了最基本的遍历集合元素的功能,支持foreach
循环。 -
实现类: 大多数集合类都实现了
IEnumerable<T>
接口,因此可以使用foreach
循环或 LINQ 查询对其进行迭代操作。
ICollection<T>:
-
功能:
ICollection<T>
继承自IEnumerable<T>
,并扩展了集合的功能。它提供了对集合进行增、删、查等操作的方法,比如Add()
、Remove()
、Contains()
等。 -
特性:
ICollection<T>
包含了一系列对集合进行操作的方法,使得可以对集合进行修改,而不仅仅是简单的迭代。 -
实现类: 一些集合类如
List<T>
、Dictionary<TKey, TValue>
等实现了ICollection<T>
接口,因此可以对其进行添加、删除和其他修改操作。
List<T>
List<T>
是 C# 中常用的动态数组集合类型,它实现了 IList<T>
接口,提供了对列表进行操作的一系列方法。List<T>
允许存储和操作元素集合,其大小可以根据需要动态增长或收缩。
主要特点和用法:
-
动态大小:
List<T>
的大小可以根据需要动态增长,无需提前指定大小。 -
索引访问: 可以通过索引访问元素,以及在列表中插入、删除或修改元素。
-
泛型集合:
List<T>
是泛型集合,可以存储任何指定类型的元素。
基本操作示例:
//创建 List 实例:
List<int> numbers = new List<int>(); // 创建一个整数类型的 List
//添加元素:
numbers.Add(10);
numbers.Add(20);
numbers.Add(30);
//访问元素:
int firstNumber = numbers[0]; // 通过索引访问元素
//遍历列表:
foreach (var number in numbers)
{
Console.WriteLine(number);
}
//插入和删除元素:
numbers.Insert(1, 15); // 在索引1处插入元素15
numbers.Remove(20); // 删除值为20的元素
//列表容量和数量:
int count = numbers.Count; // 获取列表中元素的数量
int capacity = numbers.Capacity; // 获取列表的当前容量(能够容纳的元素个数)
//清空列表:
numbers.Clear(); // 清空列表中的所有元素
总结:
List<T>
提供了一种灵活、动态的数组集合,适用于需要动态增长或收缩元素数量的场景。通过其提供的方法和属性,可以进行元素的添加、访问、删除和遍历等操作,是 C# 开发中常用的集合类型之一。
Dictionary<TKey, TValue>
Dictionary<TKey, TValue>
是 C# 中用于存储键值对的集合类型,它允许通过键快速访问值,每个键必须是唯一的,但值可以重复。Dictionary<TKey, TValue>
是基于哈希表实现的,具有快速查找和检索的特性。它实现了 IDictionary<TKey, TValue>
, ICollection<KeyValuePair<TKey, TValue>>
主要特点和用法:
-
键值对存储:
Dictionary<TKey, TValue>
存储键值对,每个键都是唯一的,值可以重复。 -
快速访问: 通过键可以快速查找和获取对应的值,因为内部使用哈希表实现,具有快速的检索能力。
-
泛型集合:
Dictionary<TKey, TValue>
是泛型集合,可以根据需要存储任何类型的键和值。
基本操作示例:
//创建 Dictionary 实例:
Dictionary<string, int> ages = new Dictionary<string, int>(); // 创建一个键为字符串,值为整数的 Dictionary
//添加键值对:
ages.Add("Alice", 25);
ages.Add("Bob", 30);
ages.Add("Charlie", 28);
//访问值:
int aliceAge = ages["Alice"]; // 获取键为 "Alice" 的值
//遍历键值对:
foreach (var pair in ages)
{
Console.WriteLine($"Key: {pair.Key}, Value: {pair.Value}");
}
//检查键是否存在:
bool containsKey = ages.ContainsKey("Alice"); // 检查是否存在键 "Alice"
//删除键值对:
ages.Remove("Bob"); // 删除键为 "Bob" 的键值对
//获取键或值的集合:
var keys = ages.Keys; // 获取所有键的集合
var values = ages.Values; // 获取所有值的集合
总结:
Dictionary<TKey, TValue>
是 C# 中常用的键值对集合类型,提供了快速的键值检索能力,适用于需要通过键快速查找和访问值的场景。通过其提供的方法和属性,可以对键值对进行添加、访问、删除和遍历等操作。
HashSet<T>
HashSet<T>
是 C# 中的集合类型,用于存储唯一的元素,不允许重复。它基于哈希表实现,提供了高效的集合操作,比如添加、删除和查找元素,同时具有判断元素是否存在的快速能力。
主要特点和用法:
-
唯一性:
HashSet<T>
中的元素是唯一的,不允许重复。如果尝试添加重复元素,将被忽略。 -
快速查找和检索:
HashSet<T>
使用哈希表实现,具有快速的查找和检索能力,对于大量数据的查找效率很高。 -
集合运算: 支持集合运算,比如并集、交集、差集等操作。
基本操作示例:
//创建 HashSet 实例:
HashSet<int> numbers = new HashSet<int>(); // 创建一个整数类型的 HashSet
//添加元素:
numbers.Add(10);
numbers.Add(20);
numbers.Add(30);
numbers.Add(20); // 尝试添加重复元素,将被忽略
//判断元素是否存在:
bool containsElement = numbers.Contains(20); // 检查元素 20 是否存在于 HashSet 中
//遍历集合:
foreach (var number in numbers)
{
Console.WriteLine(number);
}
//集合运算示例:
HashSet<int> set1 = new HashSet<int> { 1, 2, 3 };
HashSet<int> set2 = new HashSet<int> { 3, 4, 5 };
// 求并集
set1.UnionWith(set2); // 将 set1 和 set2 合并,去除重复元素
// 求交集
set1.IntersectWith(set2); // 取 set1 和 set2 的交集
// 求差集
set1.ExceptWith(set2); // 取 set1 中不属于 set2 的元素
总结:
HashSet<T>
是 C# 中用于存储唯一元素的集合类型,通过哈希表实现了高效的元素查找和检索能力。它对于需要存储不重复元素并快速判断元素是否存在的场景非常有用。除了基本的添加、删除和查找元素外,还支持集合运算等操作。
Queue<T>
Queue<T>
是 C# 中表示先进先出(FIFO)顺序的集合类型,它允许在队列的一端添加元素,在另一端移除元素,遵循先进先出的原则。Queue<T>
类位于 System.Collections.Generic
命名空间下。
主要特点和用法:
-
先进先出(FIFO):
Queue<T>
中的元素遵循先进先出的原则,最先添加的元素最先被移除。 -
基本操作: 支持向队列尾部添加元素、从队列头部移除元素、查看队列头部元素等基本操作。
基本操作示例:
//创建 Queue 实例:
Queue<int> queue = new Queue<int>(); // 创建一个整数类型的 Queue
//添加元素到队尾:
queue.Enqueue(10);
queue.Enqueue(20);
queue.Enqueue(30);
//移除队头元素:
int removedItem = queue.Dequeue(); // 移除队头元素,并返回移除的元素
//查看队头元素:
int frontItem = queue.Peek(); // 获取队头元素,但不移除它
//遍历队列:
foreach (var item in queue)
{
Console.WriteLine(item);
}
总结:
Queue<T>
是用于实现先进先出(FIFO)逻辑的集合类型,在很多情况下非常有用,比如任务排队、消息处理等场景。它提供了添加、移除和查看队列元素的方法,可以按照特定的顺序操作队列中的元素。
Stack<T>
Stack<T>
是 C# 中表示后进先出(LIFO)顺序的集合类型,它允许在栈顶添加元素和从栈顶移除元素,遵循后进先出的原则。Stack<T>
类位于 System.Collections.Generic
命名空间下。
主要特点和用法:
-
后进先出(LIFO):
Stack<T>
中的元素遵循后进先出的原则,最后添加的元素最先被移除。 -
基本操作: 支持向栈顶添加元素、从栈顶移除元素、查看栈顶元素等基本操作。
基本操作示例:
//创建 Stack 实例:
Stack<int> stack = new Stack<int>(); // 创建一个整数类型的 Stack
//添加元素到栈顶:
stack.Push(10);
stack.Push(20);
stack.Push(30);
//移除栈顶元素:
int removedItem = stack.Pop(); // 移除栈顶元素,并返回移除的元素
//查看栈顶元素:
int topItem = stack.Peek(); // 获取栈顶元素,但不移除它
//遍历栈:
foreach (var item in stack)
{
Console.WriteLine(item);
}
总结:
Stack<T>
是用于实现后进先出(LIFO)逻辑的集合类型,在许多情况下非常有用,比如实现历史记录、回退操作等。它提供了添加、移除和查看栈顶元素的方法,可以按照特定的顺序操作栈中的元素。
LinkedList<T>
LinkedList<T>
是 C# 中的双向链表集合类型,它允许按顺序存储元素,并且每个元素都包含对前一个和后一个元素的引用。LinkedList<T>
类位于 System.Collections.Generic
命名空间下。
主要特点和用法:
-
双向链表:
LinkedList<T>
使用双向链表来存储元素,每个元素都包含对前一个和后一个元素的引用,这种结构允许在链表中轻松地插入、删除元素。 -
基本操作: 支持向链表中插入元素、从链表中删除元素、访问链表中的元素等基本操作。
基本操作示例:
//创建 LinkedList 实例:
LinkedList<int> linkedList = new LinkedList<int>(); // 创建一个整数类型的双向链表
//向链表尾部添加元素:
linkedList.AddLast(10);
linkedList.AddLast(20);
linkedList.AddLast(30);
//向链表头部添加元素:
linkedList.AddFirst(5);
//删除链表中的元素:
LinkedListNode<int> node = linkedList.Find(20); // 查找元素值为 20 的节点
if (node != null)
{
linkedList.Remove(node); // 移除找到的节点
}
//遍历链表:
foreach (var item in linkedList)
{
Console.WriteLine(item);
}
注意事项:
- 在
LinkedList<T>
中,插入和删除元素的操作效率比List<T>
更高,特别是在链表中间插入或删除元素时。但是,随机访问链表中的元素效率较低,因为要遍历链表来找到特定位置的元素。
总结:
LinkedList<T>
提供了双向链表结构的集合,适用于需要频繁进行插入和删除操作的场景。它支持在链表的头部和尾部添加元素,以及按节点查找和删除元素。链表的优势在于插入和删除效率高,但访问特定位置的元素效率较低。
SortedList<TKey, TValue>
SortedList<TKey, TValue>
是 C# 中表示按键排序的集合类型,它继承自 IDictionary<TKey, TValue>
接口,并使用基于数组和二分查找树实现的内部结构。SortedList<TKey, TValue>
类位于 System.Collections.Generic
命名空间下。
主要特点和用法:
-
按键排序:
SortedList<TKey, TValue>
中的元素按键排序存储,使得键值对在集合内按键有序排列。 -
基于数组和二分查找树:
SortedList<TKey, TValue>
内部使用数组和二分查找树来实现按键排序的逻辑。
基本操作示例:
//创建 SortedList 实例:
SortedList<int, string> sortedList = new SortedList<int, string>(); // 创建一个整数键和字符串值的 SortedList
//添加键值对:
sortedList.Add(3, "Three");
sortedList.Add(1, "One");
sortedList.Add(2, "Two");
//访问键值对:
string value = sortedList[2]; // 获取键为 2 的值
//遍历键值对:
foreach (var pair in sortedList)
{
Console.WriteLine($"Key: {pair.Key}, Value: {pair.Value}");
}
//检查键是否存在:
bool containsKey = sortedList.ContainsKey(3); // 检查键 3 是否存在
注意事项:
-
SortedList<TKey, TValue>
中的键必须是唯一的,如果尝试添加重复的键,将会抛出异常。 -
添加、删除和查找元素的效率较高,因为内部使用了基于数组和二分查找树的数据结构。
总结:
SortedList<TKey, TValue>
是一个按键有序存储键值对的集合类型,适用于需要按键排序存储数据的场景。它提供了按键排序的功能,并且提供了添加、删除、查找元素等操作,内部实现的数据结构保证了这些操作的效率。
ConcurrentDictionary<TKey, TValue>
是 C# 中用于多线程并发安全操作的字典集合类型。它提供了在多线程环境下进行安全操作的能力,允许多个线程同时读取和写入不同的键值对。ConcurrentDictionary<TKey, TValue>
类位于 System.Collections.Concurrent
命名空间下。
主要特点和用法:
-
并发安全性:
ConcurrentDictionary<TKey, TValue>
提供了多线程并发安全的操作。多个线程可以同时对不同的键值对进行读取和写入操作,而不会造成数据不一致或冲突。 -
基本操作: 支持对字典进行添加、删除、更新和检索等操作,这些操作在多线程环境下是线程安全的。
-
高效性能: 内部实现采用了锁分段技术,允许多个线程并发地访问不同的段,因此在并发场景下能够提供较高的性能。
基本操作示例:
//创建 ConcurrentDictionary 实例:
ConcurrentDictionary<int, string> concurrentDictionary = new ConcurrentDictionary<int, string>(); // 创建一个整数键和字符串值的 ConcurrentDictionary
//添加键值对:
concurrentDictionary.TryAdd(1, "One");
concurrentDictionary.TryAdd(2, "Two");
concurrentDictionary.TryAdd(3, "Three");
//获取键值对:
bool found = concurrentDictionary.TryGetValue(2, out string value); // 尝试获取键为 2 的值
//更新键值对:
concurrentDictionary.TryUpdate(1, "NewValue", "One"); // 尝试更新键为 1 的值为 "NewValue"
//删除键值对:
concurrentDictionary.TryRemove(3, out string removedValue); // 尝试移除键为 3 的键值对
//遍历键值对:
foreach (var pair in concurrentDictionary)
{
Console.WriteLine($"Key: {pair.Key}, Value: {pair.Value}");
}
注意事项:
-
ConcurrentDictionary<TKey, TValue>
在处理并发操作时提供了线程安全的操作,但在某些情况下可能需要考虑锁竞争带来的性能问题。 -
在高并发场景下,
ConcurrentDictionary<TKey, TValue>
提供了一种可靠且高效的多线程安全字典实现。
总结:
ConcurrentDictionary<TKey, TValue>
是用于多线程并发安全操作的字典集合类型,适用于需要在多线程环境下进行安全操作的场景。它提供了添加、删除、更新和检索元素等操作,并确保在多线程并发访问时的线程安全性。