HashSet如何比较元素是否相等?
我有一堂课是IComparable
:
public class a : IComparable{
public int Id { get; set; }
public string Name { get; set; }
public a(int id)
{
this.Id = id;
}
public int CompareTo(object obj)
{
return this.Id.CompareTo(((a)obj).Id);
}
}
当我将此类的对象列表添加到哈希集时:
a a1 = new a(1);a a2 = new a(2);
HashSet<a> ha = new HashSet<a>();
ha.add(a1);
ha.add(a2);
ha.add(a1);
一切都很好,ha.count
还是2
,但是:
a a1 = new a(1);a a2 = new a(2);
HashSet<a> ha = new HashSet<a>();
ha.add(a1);
ha.add(a2);
ha.add(new a(1));
现在ha.count
是3
。
- 为什么不
HashSet
尊重a
的CompareTo
方法。 HashSet
拥有唯一对象列表的最佳方法是吗?
回答:
它使用一个IEqualityComparer<T>
(EqualityComparer<T>.Default
除非您在构造上指定了另一个)。
将元素添加到集合中时,它将使用来查找哈希码IEqualityComparer<T>.GetHashCode
,并存储哈希码和元素(当然,在检查元素是否已在集合中之后)。
要查找一个元素,它将首先使用IEqualityComparer<T>.GetHashCode
来查找哈希码,然后对于具有相同哈希码的所有元素,它将IEqualityComparer<T>.Equals
用于比较实际相等性。
这意味着您有两个选择:
- 将自定义传递给
IEqualityComparer<T>
构造函数。如果您不能修改T
自身,或者想要一个非默认的相等关系(例如,“所有具有负用户ID的用户都被视为相等”),则这是最佳选择。这几乎从未在类型本身上实现(即Foo
未实现IEqualityComparer<Foo>
),而是在单独的类型中仅用于比较。 - 通过覆盖
GetHashCode
和实现类型本身的相等性Equals(object)
。理想情况下,也要IEquatable<T>
在类型中实现,尤其是在它是值类型时。这些方法将由默认的相等比较器调用。
请注意,从 顺序 比较的角度来看,这些都不是什么-这很有意义,因为在某些情况下,您可以轻松指定相等性但不能指定总顺序。Dictionary<TKey,
TValue>基本上与都一样。
如果要使用 排序 而不是相等比较的集合,则应SortedSet<T>
从.NET 4 使用-
允许您指定一个IComparer<T>
而不是一个IEqualityComparer<T>
。这将使用IComparer<T>.Compare
-将委派给,IComparable<T>.CompareTo
或者IComparable.CompareTo
如果您正在使用Comparer<T>.Default
。
以上是 HashSet如何比较元素是否相等? 的全部内容, 来源链接: utcz.com/qa/416905.html