为什么不';t在.NET中,哈希表和字典使用Equals()方法而不是GetHashCode进行键比较

本文关键字:方法 Equals 比较 GetHashCode NET 字典 哈希表 为什么不 | 更新日期: 2023-09-27 18:29:58

在.NET中,每当我们重写类的Equals()方法时,通常也会重写GetHashCode()方法。这样做可以确保在Hashtables和Dictionaries中使用对象时获得更好的性能。只有当两个键的GetHashCode()值相同时,才认为它们在Hashtable中相等。我的问题是,为什么Hashtables不能使用Equals()方法来比较键?,这将消除重写GetHashCode()方法的负担。

为什么不';t在.NET中,哈希表和字典使用Equals()方法而不是GetHashCode进行键比较

HastTable/Dictionaries在发生冲突时使用Equals(当两个哈希代码相同时)

为什么他们不只使用Equals

因为这将比访问/(比较)整数值(哈希代码)需要更多的处理(由于散列码被用作索引,因此它们具有O(1)的复杂性)

HashSet(或HashTable,或Dictionary)使用一个bucket数组来分发项目,这些bucket由对象的哈希代码(应该是不可变的)索引,因此项目所在bucket的搜索为O(1)。

然后,如果有多个项目具有相同的哈希代码,则它使用该bucket中的Equals来查找完全匹配:这是O(N),因为它需要迭代该bucket内的所有项目来查找匹配。

如果一个哈希集只使用Equals,那么查找一个项将是O(N),您也可以使用列表或数组。

这也是为什么两个相等的项目必须具有相同的哈希代码,但具有相同哈希代码的两个项目不一定需要相等。

  • 比较为相等的两个对象实例必须始终具有相同的哈希代码。如果这不成立,基于哈希的数据结构将无法正常工作。这不是表现的问题
  • 理想情况下,两个比较不相等的对象实例应该具有不同的哈希代码。如果这种情况不成立,基于哈希的数据结构的性能会降低,但至少它们仍然可以工作

因此,对于给定的对象实例,GetHashCode需要在某种程度上反映Equals的逻辑。

现在,如果您正在重写Equals方法,那么您将提供自定义的比较逻辑。举个例子,假设您的自定义比较逻辑只涉及实例的一个特定数据成员。要使非虚拟GetHashCode方法有用,它必须足够通用,才能理解您的自定义Equals逻辑,并能够当场提出自定义哈希代码函数(只涉及您选择的数据成员)。

编写这样一个复杂的GetHashCode并不容易,当用户可以简单地提供一个满足初始需求的自定义单行时,也不值得麻烦。