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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/78113.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL之DML(查询语句:select、where)

&#x1f3af; 本文专栏&#xff1a;MySQL深入浅出 &#x1f680; 作者主页&#xff1a;小度爱学习 select查询语句 在开发中&#xff0c;查询语句是使用最多&#xff0c;也是CRUD中&#xff0c;复杂度最高的sql语句。 查询的语法结构 select *|字段1 [, 字段2 ……] from 表…

vue | 不同 vue 版本对复杂泛型的支持情况 · vue3.2 VS vue3.5

省流总结&#xff1a;defineProps 的泛型能力&#xff0c;来直接推导第三方组件的 props 类型 引入第三方库的类型&#xff0c;并直接在 <script setup> 中作为 props 使用。这种类型一般是复杂泛型&#xff08;包含联合类型、可选属性、交叉类型、条件类型等&#xff0…

Unity-无限滚动列表实现Timer时间管理实现

今天我们来做一个UI里经常做的东西&#xff1a;无限滚动列表。 首先我们得写清楚实现的基本思路&#xff1a; 所谓的无限滚动当然不是真的无限滚动&#xff0c;我们只要把离开列表的框再丢到列表的后面就行&#xff0c;核心理念和对象池是类似的。 我们来一点一点实现&#x…

Docker的基本概念和一些运用场景

Docker 是一种开源的容器化平台&#xff0c;可以帮助开发人员更加高效地打包、发布和运行应用程序。以下是 Docker 的基本概念和优势&#xff1a; 基本概念&#xff1a; 容器&#xff1a;Docker 使用容器来打包应用程序及其依赖项&#xff0c;容器是一个独立且可移植的运行环境…

Unity中基于第三方插件扩展的对于文件流处理的工具脚本

在Unity的项目中对应文件处理,在很多地方用到,常见的功能,就是保存文件,加载文件,判断文件或者文件夹是否存在,删除文件等。 在之前已经写过通过C#的IO实现的这些功能,可查看《Unity C# 使用IO流对文件的常用操作》,但是不能保证所有平台都可以使用 现在基于第三方跨…

Flink介绍——实时计算核心论文之MillWheel论文详解

引入 通过前面的文章&#xff0c;我们从S4到Storm&#xff0c;再到Storm结合Kafka成为当时的实时处理最佳实践&#xff1a; S4论文详解S4论文总结Storm论文详解Storm论文总结Kafka论文详解Kafka论文总结 然而KafkaStorm的第一代流式数据处理组合&#xff0c;还面临的三个核心…

python异步协程async调用过程图解

1.背景&#xff1a; 项目中有用到协程&#xff0c;但是对于协程&#xff0c;线程&#xff0c;进程的区别还不是特别了解&#xff0c;所以用图示的方式画了出来&#xff0c;用于理清三者的概念。 2.概念理解&#xff1a; 2.1协程&#xff0c;线程&#xff0c;进程包含关系 一…

【React】获取元素距离页面顶部的距离

文章目录 代码实现 代码实现 import { useEffect, useRef, useState } from react;const DynamicPositionTracker () > {const [distance, setDistance] useState(0);const divRef useRef(null);useEffect(() > {const targetDiv divRef.current;if (!targetDiv) re…

26.OpenCV形态学操作

OpenCV形态学操作 形态学操作&#xff08;Morphological Operations&#xff09;源自二值图像处理&#xff0c;主要用于分析和处理图像中的结构元素&#xff0c;对图像进行去噪、提取边缘、分割等预处理步骤。OpenCV库中提供了丰富的形态学函数&#xff0c;常见的包括&#xf…

逻辑回归:损失和正则化技术的深入研究

逻辑回归&#xff1a;损失和正则化技术的深入研究 引言 逻辑回归是一种广泛应用于分类问题的统计模型&#xff0c;尤其在机器学习领域中占据着重要的地位。尽管其名称中包含"回归"&#xff0c;但逻辑回归本质上是一种分类算法。它的核心思想是在线性回归的基础上添…

大模型面经 | 介绍一下CLIP和BLIP

大家好,我是皮先生!! 今天给大家分享一些关于大模型面试常见的面试题,希望对大家的面试有所帮助。 往期回顾: 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题一) 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题二) 大模型面经 | 春招、秋招算法…

【MCP】第二篇:IDE革命——用MCP构建下一代智能工具链

【MCP】第二篇&#xff1a;IDE革命——用MCP构建下一代智能工具链 一、引言二、IDE集成MCP2.1 VSCode2.1.1 安装VSCode2.1.2 安装Cline2.1.3 配置Cline2.1.4 环境准备2.1.5 安装MCP服务器2.1.5.1 自动安装2.1.5.2 手动安装 2.2 Trae CN2.2.1 安装Trae CN2.2.2 Cline使用2.2.3 内…

【新能源科学与技术】MATALB/Simulink小白教程(一)实验文档【新能源电力转换与控制仿真】

DP读书&#xff1a;新能源科学与工程——专业课「新能源发电系统」 2025a 版本 MATLAB下面进入正题 仿真一&#xff1a;Buck 电路一、仿真目的二、仿真内容&#xff08;一&#xff09;Buck电路基本构成及工作原理&#xff08;二&#xff09;Buck电路仿真模型及元件连接&#xf…

BootStrap:首页排版(其一)

今天我要介绍的是在BootStrap中有关于首页排版的内容知识点&#xff0c;即&#xff08;模态框&#xff0c;选项卡&#xff09;。 模态框&#xff1a; 模态框经过了优化&#xff0c;更加灵活&#xff0c;以弹出对话框的形式出现&#xff0c;具有最小和最实用的功能集。 在运行…

Spring Data

目录 一、Spring Data 简介与生态概览 什么是 Spring Data&#xff1f; Spring Data 与 Spring Data JPA 的关系 Spring Data 家族&#xff1a;JPA、MongoDB、Redis、Elasticsearch、JDBC、R2DBC…… 与 MyBatis 的本质差异&#xff08;ORM vs SQL 显式控制&#xff09; 二…

建筑末端配电回路用电安全解决方案

一、电气火灾的严峻现状 根据国家应急管理部消防救援局的数据&#xff0c;电气火灾长期占据各类火灾原因之首&#xff0c;2021年占比高达50.4%。其中&#xff0c;末端配电回路因保护不足、监测手段落后&#xff0c;成为火灾高发隐患点。私拉电线、线路老化、接触不良、过载等问…

华为开发岗暑期实习笔试(2025年4月16日)

刷题小记&#xff1a; 第一题怀疑测试样例不完整&#xff0c;贪心法不应该能够解决该题。第二题使用0-1BFS解决单源最短路径的问题&#xff0c;往往搭配双端队列实现。第三题是运用动态规划解决最大不重叠子区间个数的问题&#xff0c;难点在于满足3重判断规则&#xff0c;所需…

Rust: 从内存地址信息看内存布局

内存布局其实有几个&#xff1a;address&#xff08;地址&#xff09;、size&#xff08;大小&#xff09;、alignment&#xff08;对齐位数&#xff0c;2 的自然数次幂&#xff0c;2&#xff0c;4&#xff0c;8…&#xff09;。 今天主要从address来看内存的布局。 说明&…

每日一题算法——两个数组的交集

两个数组的交集 力扣题目链接 我的解法&#xff1a;利用数组下标。 缺点&#xff1a;当取值范围很大时&#xff0c;浪费空间。 class Solution { public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {int count1[1001]{0…

c++ 互斥锁

为练习c 线程同步&#xff0c;做了LeeCode 1114题. 按序打印&#xff1a; 给你一个类&#xff1a; public class Foo {public void first() { print("first"); }public void second() { print("second"); }public void third() { print("third"…