HashSet如何比较元素是否相等? [英] How does HashSet compare elements for equality?

查看:366
本文介绍了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);
    }
}

当我将此类的对象列表添加到散列集:

When I add a list of object of this class to a hash set:

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 ,但是:

Everything is fine and ha.count is 2, but:

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


  1. 为什么不 HashSet 尊重 a CompareTo 方法。

  2. HashSet 拥有唯一对象列表的最佳方法?

  1. Why doesn't HashSet respect a's CompareTo method.
  2. Is HashSet the best way to have a list of unique objects?


推荐答案

它使用 IEqualityComparer< T> EqualityComparer< T>。默认 ,除非您在构造上指定了另一个)。

It uses an IEqualityComparer<T> (EqualityComparer<T>.Default unless you specify a different one on construction).

将元素添加到集合中时,它会将使用 IEqualityComparer< T> .GetHashCode 查找哈希码,并存储哈希码和元素(当然,在检查元素是否已在集合中之后)

When you add an element to the set, it will find the hash code using IEqualityComparer<T>.GetHashCode, and store both the hash code and the element (after checking whether the element is already in the set, of course).

要查找元素,它将首先使用 IEqualityCompar er< T> .GetHashCode 查找哈希码,然后对于具有相同哈希码的所有元素,它将使用 IEqualityComparer< T> ;.等于比较实际的相等性。

To look an element up, it will first use the IEqualityComparer<T>.GetHashCode to find the hash code, then for all elements with the same hash code, it will use IEqualityComparer<T>.Equals to compare for actual equality.

这意味着您有两个选择:

That means you have two options:


  • 将自定义 IEqualityComparer< T> 传递到构造函数中。如果您不能修改 T 本身,或者想要一个非默认的相等关系(例如,所有具有负用户ID的用户都被认为是等于)。这几乎永远不会在类型本身上实现(即 Foo 不实现 IEqualityComparer< Foo> ),但是在

  • 通过覆盖 GetHashCode 来实现类型本身的相等性等于(对象)。理想情况下,还要在类型中实现 IEquatable< T> ,尤其是在它是值类型的情况下。这些方法将由默认的相等比较器调用。

  • Pass a custom IEqualityComparer<T> into the constructor. This is the best option if you can't modify the T itself, or if you want a non-default equality relation (e.g. "all users with a negative user ID are considered equal"). This is almost never implemented on the type itself (i.e. Foo doesn't implement IEqualityComparer<Foo>) but in a separate type which is only used for comparisons.
  • Implement equality in the type itself, by overriding GetHashCode and Equals(object). Ideally, implement IEquatable<T> in the type as well, particularly if it's a value type. These methods will be called by the default equality comparer.

请注意,这与有序无关。 em>比较-这很有意义,因为在某些情况下,您可以轻松指定相等性,但不能指定总顺序。基本上,这与 Dictionary< TKey,TValue> 相同。

Note how none of this is in terms of an ordered comparison - which makes sense, as there are certainly situations where you can easily specify equality but not a total ordering. This is all the same as Dictionary<TKey, TValue>, basically.

如果要使用排序,而不仅仅是相等比较,您应该使用 <$ .NET 4中的c $ c> SortedSet< T> -允许您指定 IComparer< T> 而不是 IEqualityComparer< T> 。这将使用 IComparer< T> .Compare -将委托给 IComparable< T> .CompareTo IComparable.CompareTo (如果您使用的是 Comparer< T>。默认值

If you want a set which uses ordering instead of just equality comparisons, you should use SortedSet<T> from .NET 4 - which allows you to specify an IComparer<T> instead of an IEqualityComparer<T>. This will use IComparer<T>.Compare - which will delegate to IComparable<T>.CompareTo or IComparable.CompareTo if you're using Comparer<T>.Default.

这篇关于HashSet如何比较元素是否相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆