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()
    {
        // 初始化 HashSet
        Console.WriteLine("---------------------------------1、初始化--------------------------------------------");
        var hashSet = new HashSet<int> { 1, 2, 3 };
        Console.WriteLine("初始集合: " + string.Join(", ", hashSet)); // 输出: 1, 2, 3

        Console.WriteLine("---------------------------------2、增加元素--------------------------------------------");
        // 添加元素
        bool added = hashSet.Add(4);
        Console.WriteLine($"添加 4 成功?{added}"); // true

        added = hashSet.Add(2);
        Console.WriteLine($"重复添加 2 成功?{added}"); // false

        Console.WriteLine("---------------------------------3、查找元素--------------------------------------------");
        // 检查元素存在性
        Console.WriteLine("是否包含 3?" + hashSet.Contains(3)); // true

        Console.WriteLine("---------------------------------4、删除元素--------------------------------------------");
        // 删除元素
        bool removed = hashSet.Remove(2);
        Console.WriteLine($"删除 2 成功?{removed}"); // true

        Console.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, 6

        Console.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, 8

        Console.WriteLine("---------------------------------2、添加元素--------------------------------------------");
        // 添加元素
        bool added = sortedSet.Add(3);
        Console.WriteLine($"添加 3 成功?{added}"); // true

        added = sortedSet.Add(2);
        Console.WriteLine($"重复添加 2 成功?{added}"); // false

        Console.WriteLine("---------------------------------3、查询是否存在某个元素--------------------------------------------");
        // 检查元素存在性
        Console.WriteLine("是否包含 5?" + sortedSet.Contains(5)); // true

        Console.WriteLine("---------------------------------4、删除某一个元素--------------------------------------------");
        // 删除元素
        bool removed = sortedSet.Remove(8);
        Console.WriteLine($"删除 8 成功?{removed}"); // true

        Console.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, 4

        Console.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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

FAREWELL00075

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

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

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

打赏作者

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

抵扣说明:

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

余额充值