欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > C#进阶学习(七)常见的泛型数据结构类(2)HashSet和SortedSet

C#进阶学习(七)常见的泛型数据结构类(2)HashSet和SortedSet

2025/4/24 21:27:29 来源:https://blog.csdn.net/m0_74212916/article/details/147344688  浏览:    关键词:C#进阶学习(七)常见的泛型数据结构类(2)HashSet和SortedSet

        

目录

using System.Collections.Generic; // 核心命名空间

一、 HashSet

核心特性

常用方法

属性

二、SortedSet

核心特性

1、整型(int、long 等)

2、字符串型(string) 

3、字符型(char)

4、自定义对象

常用方法

属性

三、 HashSet  和 SortedSet  方法对比表

共有方法

独有方法

四、HashSet中的自定义相等方法与SortedSet中的自定义排序方式的示例 

4-1HashSet示例,不区分大小写:

4-2SortedSet自定义比较器(按字符串长度排序和倒序排数字)

五、总结


       

         注意本文提到的数据结构需在比较新的.NET框架上使用,不然会出错 

必须引用的命名空间:

using System.Collections.Generic; // 核心命名空间

一、 HashSet<T>

核心特性

  • 唯一性:保证集合中元素的唯一性(通过 GetHashCode 和 Equals 判断重复)。

  • 无序性:元素的存储和遍历顺序与插入顺序无关,也不保证任何特定顺序。

  • 底层实现:基于哈希表(Hash Table),使用桶(Buckets)和链表/开放寻址解决哈希冲突。

  • 适用场景:快速判断元素是否存在、去重、集合运算(并集、交集、差集)。

创造方式:

// 默认构造函数
var hashSet1 = new HashSet<int>();// 从集合初始化
var hashSet2 = new HashSet<int>(new[] { 1, 2, 3 });// 指定自定义相等比较器
var hashSet3 = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

 

常用方法

方法名参数返回值/行为示例代码
Add(T item)要添加的元素返回 bool(是否添加成功)hashSet.Add(5);
Remove(T item)要删除的元素返回 bool(是否删除成功)hashSet.Remove(2);
Contains(T item)要检查的元素返回 bool(是否包含元素)if (hashSet.Contains(3)) { ... }
Clear()清空所有元素hashSet.Clear();
UnionWith(IEnumerable<T>)另一个集合将当前集合修改为与另一个集合的并集hashSet.UnionWith(otherSet);
IntersectWith(IEnumerable<T>)另一个集合将当前集合修改为与另一个集合的交集hashSet.IntersectWith(otherSet);
ExceptWith(IEnumerable<T>)另一个集合将当前集合修改为当前集合减去另一个集合(差集)hashSet.ExceptWith(otherSet);
SymmetricExceptWith(IEnumerable<T>)另一个集合将当前集合修改为仅包含存在于当前集合或另一集合但不同时存在的元素(对称差集)hashSet.SymmetricExceptWith(otherSet);
IsSubsetOf(IEnumerable<T>)另一个集合返回 bool(当前集合是否是另一个集合的子集)bool isSubset = hashSet.IsSubsetOf(otherSet);
IsSupersetOf(IEnumerable<T>)另一个集合返回 bool(当前集合是否是另一个集合的超集)bool isSuperset = hashSet.IsSupersetOf(otherSet);
Overlaps(IEnumerable<T>)另一个集合返回 bool(当前集合与另一个集合是否有交集)bool overlaps = hashSet.Overlaps(otherSet);
SetEquals(IEnumerable<T>)另一个集合返回 bool(当前集合是否与另一个集合元素完全相同)bool equals = hashSet.SetEquals(otherSet);
CopyTo(T[] array)目标数组将集合元素复制到数组中int[] arr = new int[10]; hashSet.CopyTo(arr);
TryGetValue(T equalValue, out T actualValue)查找的值 equalValue如果找到相等元素,返回 true 并赋值给 actualValueif (hashSet.TryGetValue(5, out int val)) { ... }

主要使用演示:

using System;
using System.Collections.Generic;public class HashSetExample
{public static void Main(){// 初始化 HashSetConsole.WriteLine("---------------------------------1、初始化--------------------------------------------");var hashSet = new HashSet<int> { 1, 2, 3 };Console.WriteLine("初始集合: " + string.Join(", ", hashSet)); // 输出: 1, 2, 3Console.WriteLine("---------------------------------2、增加元素--------------------------------------------");// 添加元素bool added = hashSet.Add(4);Console.WriteLine($"添加 4 成功?{added}"); // trueadded = hashSet.Add(2);Console.WriteLine($"重复添加 2 成功?{added}"); // falseConsole.WriteLine("---------------------------------3、查找元素--------------------------------------------");// 检查元素存在性Console.WriteLine("是否包含 3?" + hashSet.Contains(3)); // trueConsole.WriteLine("---------------------------------4、删除元素--------------------------------------------");// 删除元素bool removed = hashSet.Remove(2);Console.WriteLine($"删除 2 成功?{removed}"); // trueConsole.WriteLine("---------------------------------5、集合运算--------------------------------------------");// 集合运算var otherSet = new HashSet<int> { 3, 4, 5 };// 并集(合并两个集合的元素)hashSet.UnionWith(otherSet);Console.WriteLine("并集后: " + string.Join(", ", hashSet)); // 1, 3, 4, 5// 交集(保留共同元素)hashSet.IntersectWith(new[] { 3, 4 });Console.WriteLine("交集后: " + string.Join(", ", hashSet)); // 3, 4// 差集(移除当前集合中与另一集合重复的元素)hashSet.ExceptWith(new[] { 3 });Console.WriteLine("差集后: " + string.Join(", ", hashSet)); // 4// 对称差集(仅保留不重复的元素)hashSet.SymmetricExceptWith(new[] { 4, 5, 6 });Console.WriteLine("对称差集后: " + string.Join(", ", hashSet)); // 5, 6Console.WriteLine("---------------------------------6、获取存在的元素使用--------------------------------------------");// TryGetValue(查找元素)if (hashSet.TryGetValue(5, out int value)){Console.WriteLine($"找到元素: {value}"); // 5}Console.WriteLine("---------------------------------7、清空元素--------------------------------------------");// 清空集合hashSet.Clear();Console.WriteLine("清空后元素数量: " + hashSet.Count); // 0}
}

 

属性

属性名类型说明示例代码
Countint集合中元素的数量int count = hashSet.Count;
ComparerIEqualityComparer<T>用于比较元素的相等性比较器var comparer = hashSet.Comparer;

         这个比较器,主要是用来自定义相同规则

二、SortedSet<T>

核心特性

  • 唯一性:保证元素唯一性。

  • 有序性:元素按升序自动排列(默认使用 IComparer<T> 或元素的自然顺序)。

  • 底层实现:基于红黑树(Red-Black Tree),一种自平衡二叉搜索树。

  • 适用场景:需要有序唯一元素的集合、范围查询(如获取某个区间内的元素)。

        这个排序指的是怎么个排序法则呢:

SortedSet<T> 默认按元素的 自然顺序(IComparable<T> 接口)排序

看都看不懂上面那句话,来我们接着往下看,对于不同的类型具有不同的排序方式:

1、整型(intlong 等)

按数值升序排列。

示例:{ 5, 3, 9 } → 排序后为 { 3, 5, 9 }

2、字符串型(string 

按字典序(区分大小写)排序。

示例:{ "Banana", "apple", "Cherry" } → 排序后为 { "Banana", "Cherry", "apple" }(ASCII 值:B=66C=67a=97)。

3、字符型(char

按 Unicode 码点升序排序。

示例:{ 'C', 'a', '1' } → 排序后为 { '1' (U+0031), 'C' (U+0043), 'a' (U+0061) }

4、自定义对象

        若未实现 IComparable<T>,需通过构造函数指定 IComparer<T>,否则会抛出异常。

初始化方式:

// 默认构造函数(按自然顺序排序)
var sortedSet1 = new SortedSet<int>();// 从集合初始化
var sortedSet2 = new SortedSet<int>(new[] { 3, 1, 2 });// 指定自定义比较器
var sortedSet3 = new SortedSet<string>(StringComparer.OrdinalIgnoreCase);

 

常用方法

方法名参数返回值/行为示例代码
Add(T item)要添加的元素返回 bool(是否添加成功)sortedSet.Add(5);
Remove(T item)要删除的元素返回 bool(是否删除成功)sortedSet.Remove(2);
Contains(T item)要检查的元素返回 bool(是否包含元素)if (sortedSet.Contains(3)) { ... }
Clear()清空所有元素sortedSet.Clear();
UnionWith(IEnumerable<T>)另一个集合将当前集合修改为与另一个集合的并集sortedSet.UnionWith(otherSet);
IntersectWith(IEnumerable<T>)另一个集合将当前集合修改为与另一个集合的交集sortedSet.IntersectWith(otherSet);
ExceptWith(IEnumerable<T>)另一个集合将当前集合修改为当前集合减去另一个集合(差集)sortedSet.ExceptWith(otherSet);
SymmetricExceptWith(IEnumerable<T>)另一个集合将当前集合修改为仅包含存在于当前集合或另一集合但不同时存在的元素(对称差集)sortedSet.SymmetricExceptWith(otherSet);
GetViewBetween(T lower, T upper)下限 lower 和上限 upper返回一个子集视图,包含介于 lower 和 upper 之间的元素var subset = sortedSet.GetViewBetween(2, 5);
CopyTo(T[] array)目标数组将集合元素复制到数组中int[] arr = new int[10]; sortedSet.CopyTo(arr);
Reverse()返回一个按降序排列的 IEnumerable<T>foreach (var item in sortedSet.Reverse()) { ... }

使用演示:

using System;
using System.Collections.Generic;public class SortedSetExample
{public static void Main(){Console.WriteLine("---------------------------------1、初始化--------------------------------------------");// 初始化 SortedSet(默认升序)var sortedSet = new SortedSet<int> { 5, 2, 8, 1 };Console.WriteLine("初始集合: " + string.Join(", ", sortedSet)); // 1, 2, 5, 8Console.WriteLine("---------------------------------2、添加元素--------------------------------------------");// 添加元素bool added = sortedSet.Add(3);Console.WriteLine($"添加 3 成功?{added}"); // trueadded = sortedSet.Add(2);Console.WriteLine($"重复添加 2 成功?{added}"); // falseConsole.WriteLine("---------------------------------3、查询是否存在某个元素--------------------------------------------");// 检查元素存在性Console.WriteLine("是否包含 5?" + sortedSet.Contains(5)); // trueConsole.WriteLine("---------------------------------4、删除某一个元素--------------------------------------------");// 删除元素bool removed = sortedSet.Remove(8);Console.WriteLine($"删除 8 成功?{removed}"); // trueConsole.WriteLine("---------------------------------5、集合运算--------------------------------------------");// 集合运算var otherSet = new SortedSet<int> { 3, 4, 5 };// 并集sortedSet.UnionWith(otherSet);Console.WriteLine("并集后: " + string.Join(", ", sortedSet)); // 1, 2, 3, 4, 5// 交集sortedSet.IntersectWith(new[] { 2, 3, 4 });Console.WriteLine("交集后: " + string.Join(", ", sortedSet)); // 2, 3, 4// 范围查询(获取介于 3 和 5 之间的元素视图)var subset = sortedSet.GetViewBetween(3, 5);Console.WriteLine("范围查询结果: " + string.Join(", ", subset)); // 3, 4Console.WriteLine("---------------------------------5、最大值最小值--------------------------------------------");// 直接获取最小值和最大值Console.WriteLine($"最小值: {sortedSet.Min}, 最大值: {sortedSet.Max}"); // 2, 4// 逆序遍历(降序)Console.Write("逆序遍历: ");foreach (var num in sortedSet.Reverse()){Console.Write(num + " "); // 4, 3, 2}Console.WriteLine();// 清空集合sortedSet.Clear();Console.WriteLine("清空后元素数量: " + sortedSet.Count); // 0}
}

 

属性

属性名类型说明示例代码
Countint集合中元素的数量int count = sortedSet.Count;
ComparerIComparer<T>用于排序元素的比较器var comparer = sortedSet.Comparer;
MinT集合中的最小元素int min = sortedSet.Min;
MaxT集合中的最大元素int max = sortedSet.Max;

 

三、 HashSet<T> 和 SortedSet<T> 方法对比表

共有方法

方法名HashSet<T> 支持SortedSet<T> 支持说明
Add(T)✔️✔️添加元素
Remove(T)✔️✔️删除元素
Contains(T)✔️✔️检查元素是否存在
Clear()✔️✔️清空集合
UnionWith(IEnumerable<T>)✔️✔️并集操作
IntersectWith(IEnumerable<T>)✔️✔️交集操作
ExceptWith(IEnumerable<T>)✔️✔️差集操作
SymmetricExceptWith(IEnumerable<T>)✔️✔️对称差集操作
CopyTo(T[])✔️✔️复制到数组

独有方法

方法名HashSet<T> 特有SortedSet<T> 特有说明
TryGetValue(T, out T)✔️查找并返回元素(哈希表特性)
GetViewBetween(T, T)✔️获取子集视图(有序特性)
Reverse()✔️返回降序迭代器(有序特性)
Min / Max✔️直接获取最小/最大值(有序特性)

四、HashSet中的自定义相等方法与SortedSet中的自定义排序方式的示例 

4-1HashSet示例,不区分大小写:

第一步,实现一个IEqualityComparer接口
//比较接口
public class InsensitiveComparer : IEqualityComparer<string>
{//判断两个字符串是否相等 不判断类型public bool Equals(string? x, string? y){//使用系统给我们实现好的 直接忽略大小写return string.Equals(x,y,StringComparison.OrdinalIgnoreCase);}//生成字符串的哈希码(不区分大小写)public int GetHashCode([DisallowNull] string obj){//将字符串统一转为大写后生成哈希码return obj.ToUpper().GetHashCode();}
}
第二步,在初始化集合时new 一个接口,这里是里氏替换原则哦
HashSet<string> haseSetString = new HashSet<string>(new InsensitiveComparer())
{"Apple","apple","Banana"
};
Console.WriteLine(haseSetString.Count);
Console.WriteLine(haseSetString.Contains("APPLE"));

 

4-2SortedSet自定义比较器(按字符串长度排序和倒序排数字)

第一步、实现IComparer接口:
public class StringLengthComparer : IComparer<string>
{public int Compare(string? x, string? y){// 按长度升序,若长度相同则按字典序int lengthCompare = x.Length.CompareTo(y.Length);return lengthCompare != 0 ? lengthCompare : string.Compare(x, y, StringComparison.Ordinal);}
}public class ReverseIntComparer : IComparer<int>
{public int Compare(int x, int y){// 默认升序是 x.CompareTo(y),降序则反转//y 比较与 x//谁小 谁放前return y.CompareTo(x);}
}
第二步、初始化时new 一个接口对象
//1.自定义字符串长度使用
var sortedSetString = new SortedSet<string>(new StringLengthComparer())
{"Banana", "Apple", "Cherry", "Kiwi"
};
Console.WriteLine("按长度排序:");
foreach (var item in sortedSet)
{Console.WriteLine(item); // 输出顺序:Kiwi → Apple → Banana → Cherry
}//2.倒序排数字
// 使用自定义比较器初始化 SortedSet
var sortedSetInt = new SortedSet<int>(new ReverseIntComparer())
{5, 3, 9, 1
};Console.WriteLine("降序排序:");
foreach (var num in sortedSetInt)
{Console.Write(num + " "); // 输出:9 5 3 1
}
#endregion

五、总结

HashSet<T> 的核心是快速查找和集合运算,适用于无序唯一集合

SortedSet<T> 的核心是维护有序性和范围查询,适用于需要排的场景。

两者共享大部分集合操作方法,但 SortedSet<T> 额外提供有序相关的功能(如 MinMaxGetViewBetween)。

根据需求选择:

速度优先 → HashSet<T>

顺序优先 → SortedSet<T>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词