C#泛型集合详解:SortedList、Dictionary与Set的选型指南
在C#开发中,正确选择泛型集合能显著提升程序性能。本文涵盖SortedList、Dictionary、SortedDictionary的内部机制与API操作,解析LinkedList的结构特点,并对比HashSet与SortedSet在数据集处理中的应用场景。
SortedList<TKey, TValue>:有序且紧凑的键值对
SortedList类似于List<T>,但其内部元素按键自动排序。添加元素时需使用键值对,系统通过二分查找确定插入位置,并将后续元素整体后移。这种结构使得内存占用较少,但插入操作的开销相对较大,适合数据插入不频繁但查找频繁的场景。
static void Main(string[] args)
{
var mySotedList = new SortedList<int, string>();
mySotedList.Add(1, "张三");
mySotedList.Add(2,"李四");
mySotedList.Add(3,"赵六");
mySotedList.Add(4,"王九");
//判断是否包含某个键
bool hasKey = mySotedList.ContainsKey(1);
//判断是否包含某个值
bool hasValue = mySotedList.ContainsValue("张三");
//获取某个键的索引
int keyIndex = mySotedList.IndexOfKey(2);
//获取某个值的索引
int valIndex = mySotedList.IndexOfValue("李四");
//根据键删除
mySotedList.Remove(3);
//根据索引删除
mySotedList.RemoveAt(1);
//根据键查找元素
string myVal = mySotedList[3];
//根据索引查找元素
string myVal1 = mySotedList.Values[1];
//根据索引查找键
int myKey = mySotedList.Keys[3];
//获取某个元素而不抛异常
string myWantVal;
if (mySotedList.TryGetValue(2, out myWantVal))
{
// 找到了 myWantVal
}
//遍历键
foreach (int key in mySotedList.Keys)
{
}
//遍历值
foreach (string str in mySotedList.Values)
{
}
}Dictionary<TKey, TValue>:高效的哈希表
Dictionary基于HashTable实现,以键值对存储数据。其键必须唯一,且元素无序。相比SortedList,Dictionary在插入和查找时的效率更高,是处理大量数据插入和不需排序场景的首选。
var myDictionary = new Dictionary<int, string>();
myDictionary.Add(1, "darren");
myDictionary.Add(2, "jack");
myDictionary.Add(3, "sunny");
//根据键判断是否存在
bool exists = myDictionary.ContainsKey(1);
//根据值判断是否存在
bool valExists = myDictionary.ContainsValue("darren");
//根据键删除
myDictionary.Remove(3);
//根据键查找集合元素
string myVal = myDictionary[2];
//根据键查找元素不抛异常
string myVal1;
if (myDictionary.TryGetValue(2, out myVal1))
{
}
//遍历键
foreach (int key in myDictionary.Keys)
{
}
//遍历值
foreach (string value in myDictionary.Values)
{
}SortedDictionary<TKey, TValue>:自平衡红黑树
SortedDictionary同样维护有序键值对,但与SortedList不同,它内部采用红黑树实现。这不允许通过索引访问元素,但在频繁插入时比SortedList拥有更好的执行效率,尽管会占用更多内存。
var mySortedDictionary = new SortedDictionary<int, string>();
mySortedDictionary.Add(1,"one");
mySortedDictionary.Add(2,"two");
mySortedDictionary.Add(3,"three");
//判断是否包含某个键
bool hasKey = mySortedDictionary.ContainsKey(2);
//判断是否包含某个值
bool hasValue = mySortedDictionary.ContainsValue("two");
//根据键移除某个元素
mySortedDictionary.Remove(2);
//根据键查找某个元素
string myVal = mySortedDictionary[1];
//根据键查找元素,不抛异常
string myVal1;
if (mySortedDictionary.TryGetValue(1, out myVal1))
{
}
//遍历所有键
foreach (int key in mySortedDictionary.Keys)
{
}
//遍历所有值
foreach (string val in mySortedDictionary.Values)
{
}LinkedList<T>:灵活的双向链表
LinkedList每个节点都指向前驱和后继节点,形成环形双向链表。它在任意位置插入或删除节点的开销较小,非常适合频繁的批量插入操作。支持通过Find方法定位特定节点,或按First/Last直接访问头尾。
var myLinkedList = new LinkedList<string>();
//创建第一个节点
myLinkedList.AddFirst("one");
//创建最后一个节点
var lastNode = myLinkedList.AddLast("three");
//在最后一个节点前添加一个节点
myLinkedList.AddBefore(lastNode, "two");
//在当前最后一个节点后面添加一个节点
myLinkedList.AddAfter(lastNode, "four");
//遍历节点值
foreach (string value in myLinkedList)
{
}
//根据值查找节点
//找到符合条件的第一个节点
var myNode = myLinkedList.Find("two");
//根据值查找节点
//找到符合条件的最后一个节点
var myNode1 = myLinkedList.FindLast("one");
//获取第一个节点
var firstNode = myLinkedList.First;
//获取最后一个节点
var lastNode1 = myLinkedList.Last;
//根据值产生节点
myLinkedList.Remove("one");
//删除第一个节点
myLinkedList.RemoveFirst();
//删除最后一个节点
myLinkedList.RemoveLast();
//清空所有节点
myLinkedList.Clear();SortedSet<T>与HashSet<T>:集合运算
这两个类均实现了ISet接口,用于处理唯一元素集。SortedSet内部由红黑树驱动,保持元素顺序,适合需要范围查询或排序的场景;而HashSet基于哈希表,查询速度更快,适用于大多数不需要排序的去重和集合运算场景。
SortedSet 核心用法
代表一个抽象的数据集,元素唯一且已排序。常用于数学意义上的集合操作,如求交集、并集、差集等。
var sortedSet1 = new SortedSet<string>();
sortedSet1.Add("one");
sortedSet1.Add("two");
sortedSet1.Add("three");
var sortedSet2 = new SortedSet<string>();
sortedSet2.Add("two");
sortedSet2.Add("four");
//判断某个值是否存在
bool contains = sortedSet1.Contains("one");
//合并数据集,取出重复项(差集:sortedSet1中有但sortedSet2中没有的)
sortedSet1.ExceptWith(sortedSet2);
//判断一个数据集是否是另一个数据集的子集
bool isSubset = sortedSet1.IsSubsetOf(sortedSet2);
//判断两个数据集是否有交集
bool overlaps = sortedSet1.Overlaps(sortedSet2);
//根据值删除某个元素
sortedSet1.Remove("two");
//判断两个数据集是否相等
bool equals = sortedSet1.SetEquals(sortedSet2);
//只包含在一个数据集中的元素,这些元素不包含在另一个数据集(对称差集)
sortedSet1.SymmetricExceptWith(sortedSet2);
//取两个数据集的并集
sortedSet1.UnionWith(sortedSet2);
//获取包含某些元素的数据集视图
SortedSet<string> result = sortedSet1.GetViewBetween("one", "two");
//遍历数据集
foreach (string val in sortedSet1)
{
}
//清空数据集
sortedSet1.Clear();HashSet 核心用法
当需要根据多个元素值作为查找条件,或者数据无法哈希时使用SortedSet;其余大多数情况,尤其是追求性能的集合运算,应优先使用HashSet。
var hashSet1 = new HashSet<string>();
hashSet1.Add("one");
hashSet1.Add("two");
hashSet1.Add("three");
var hashSet2 = new HashSet<string>();
hashSet2.Add("two");
hashSet2.Add("four");
//判断是否包含某个值
bool contains = hashSet1.Contains("four");
//去掉一个数据集中与另一个数据集重复的项(差集)
hashSet1.ExceptWith(hashSet2);
//保留一个数据集中与另一个数据集相同的项(交集)
hashSet1.IntersectWith(hashSet2);
//判断一个数据集是否是另一个数据集的子集
bool isSubset = hashSet1.IsSubsetOf(hashSet2);
//判断一个数据集是否包含另一个数据集的所有元素(超集)
bool isSuperset = hashSet1.IsSupersetOf(hashSet2);
//判断两个数据集是否有重复的元素
bool overlaps = hashSet1.Overlaps(hashSet2);
//根据值删除某个元素
hashSet1.Remove("one");
//判断两个数据集是否相等
bool equals = hashSet1.SetEquals(hashSet2);
//合并两个数据集(并集)
hashSet1.UnionWith(hashSet2);
//查找只包含在一个数据集中,却不包含在另一个数据集的元素(对称差集)
hashSet1.SymmetricExceptWith(hashSet2);
//遍历数据集
foreach (string value in hashSet1)
{
}
//清空数据集
hashSet1.Clear();总结与选型建议
- Stack<T>:先进后出(LIFO)。
- Queue<T>:先进先出(FIFO)。
- SortedList<TKey, TValue>:插入不频繁,查找频繁,需要索引访问。
- Dictionary<TKey, TValue>:频繁插入,无需排序,纯哈希查找。
- SortedDictionary<TKey, TValue>:频繁插入,需要排序,但不需要随机索引访问。
- LinkedList<T>:大量的中间插入或删除操作。
- SortedSet<T>:需要对数据进行排序后的集合运算,或范围查询。
- HashSet<T>:大多数去重和集合运算场景,性能优先。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













