C#:HashSet<T> 去重

HashSet<T> 底层基于哈希表实现,去重依赖 `GetHashCode()` 和 `Equals()` 两个方法。添加元素时,先计算哈希码定位桶位置,若哈希冲突则调用 `Equals()` 比较内容。若两者均判定相等,则视为重复元素不予添加。

关键机制:
1. 哈希分流:通过 `GetHashCode()` 快速定位存储桶,平均时间复杂度 O(1)。
2. 精确比对:哈希值相同(冲突)时,才执行 `Equals()` 进行逐字段比较。
3. 契约约束:若 `Equals()` 返回 true,`GetHashCode()` 必须返回相同值;反之不成立。

常见陷阱与修复:
*   引用类型默认行为:未重写上述两方法时,默认比较内存地址,导致内容相同的不同对象被视为不重复。
*   性能优化:`Add()` 返回 bool 值,直接利用返回值判断是否为新元素,避免额外调用 `Contains()` 造成二次哈希查找。
using System;
using System.Collections.Generic;

// 方案1:使用 record (C9+),编译器自动生成正确的 GetHashCode 和 Equals
public record Person(string Name, int Age);

// 方案2:传统 class 需手动重写
public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        if (obj is Product other)
            return Id == other.Id; // 根据业务主键判断
        return false;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(Id); // 确保参与 Equals 的字段也参与哈希计算
    }
}

class Program
{
    static void Main()
    {
        // 1. 基础类型去重 (int/string 已内置正确实现)
        var numbers = new List<int> { 1, 2, 2, 3, 4, 4, 5 };
        var uniqueNumbers = new HashSet<int>(numbers); // 构造函数直接去重
        
        Console.WriteLine($"Unique Numbers: {string.Join(", ", uniqueNumbers)}");

        // 2. 复杂对象去重 (使用 record)
        var people = new List<Person>
        {
            new Person("Alice", 25),
            new Person("Bob", 30),
            new Person("Alice", 25) // 重复
        };
        var uniquePeople = new HashSet<Person>(people);
        
        // 3. 流式处理去重 (利用 Add 返回值,避免二次查找)
        var rawIds = new List<string> { "A01", "A02", "A01", "A03" };
        var seenIds = new HashSet<string>();
        foreach (var id in rawIds)
        {
            if (seenIds.Add(id)) // Add 返回 true 表示是新元素,false 表示已存在
            {
                Console.WriteLine($"Processing new ID: {id}");
            }
        }
    }
}
```

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值