C# HashSet添加两个同值List<int>后计数为2的原因是什么?
C# HashSet<List> 未按预期去重问题
复现代码
HashSet<List<int>> hs = new HashSet<List<int>>(); List<int> list1 = new List<int>(); list1.Add(1); list1.Add(2); List<int> list2 = new List<int>(); list2.Add(1); list2.Add(2); hs.Add(list1); hs.Add(list2); Console.WriteLine(hs.Count);
现象描述
运行上述代码后,控制台输出hs.Count的结果为2,不符合HashSet去重的预期(预期输出1),实现相同逻辑的Java代码运行输出结果为1。
原因说明
- 核心差异来自两门语言中List类型的相等性判断规则完全不同:
- Java的List接口强制所有实现类重写
equals()和hashCode()方法:只要两个List的元素顺序、元素值完全一致,哪怕是独立new出来的不同实例,也会被判定为相等,哈希值也基于元素内容计算。因此Java的HashSet会把内容相同的两个List识别为重复元素,最终计数为1。 - C#的
List<T>作为引用类型,没有重写基类object的Equals()和GetHashCode()方法,默认走引用相等判定逻辑:只有两个引用指向内存中同一个对象实例时,才会判定为相等,哈希值也和实例的内存引用绑定。
- Java的List接口强制所有实现类重写
- 代码中的
list1和list2是分别实例化的两个独立对象,虽然存储的元素完全一致,但内存地址不同,C#默认的相等比较器会将二者识别为不同元素,HashSet不会执行去重逻辑,最终输出Count为2是符合C#语言设计规则的结果。
如果需要在C#中实现基于List内容的去重,初始化HashSet时传入自定义的
IEqualityComparer<List<int>>实现,自行编写基于元素内容的相等判断和哈希值计算逻辑即可。
内容的提问来源于stack exchange,提问作者Siddharth b
相关产品推荐
相关产品推荐

