为什么不';t在.NET中,哈希表和字典使用Equals()方法而不是GetHashCode进行键比较
本文关键字:方法 Equals 比较 GetHashCode NET 字典 哈希表 为什么不 | 更新日期: 2023-09-27 18:29:58
在.NET中,每当我们重写类的Equals()方法时,通常也会重写GetHashCode()方法。这样做可以确保在Hashtables和Dictionaries中使用对象时获得更好的性能。只有当两个键的GetHashCode()值相同时,才认为它们在Hashtable中相等。我的问题是,为什么Hashtables不能使用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
并不容易,当用户可以简单地提供一个满足初始需求的自定义单行时,也不值得麻烦。