HashSet<T>.Add
首先比较GetHashCode
的结果。如果它们相等,它会调用Equals
。
据我所知,为了实现GetHashCode
,必须对对象的字段进行一些操作。可以在这里找到一个简单的示例实现。
在我的测试中,使用1,000,000个填充了随机数据的对象对进行比较,两者的性能差不多。其中GetHashCode
的实现方法是链接示例中的方式,Equals
只是对所有字段调用Equals
。那么为什么要使用GetHashCode
而不是Equals
?
HashSet<T>.Add
首先比较GetHashCode
的结果。如果它们相等,它会调用Equals
。
据我所知,为了实现GetHashCode
,必须对对象的字段进行一些操作。可以在这里找到一个简单的示例实现。
在我的测试中,使用1,000,000个填充了随机数据的对象对进行比较,两者的性能差不多。其中GetHashCode
的实现方法是链接示例中的方式,Equals
只是对所有字段调用Equals
。那么为什么要使用GetHashCode
而不是Equals
?
Equals
测试可能会比较昂贵。这通常需要比较类的每个字段。换句话说,它与类大小呈线性关系。较大的类比较相等的代价更高。Equals
1000次可能会变得很昂贵。如果N是类的大小,则需要进行N*2000个字段访问。
GetHashCode
生成基于类内容的“几乎唯一”的整数。换句话说,只需要访问一次类字段。一旦有了这个值,就可以将此整数与组成其他对象哈希码的1000个整数进行比较。因为如果一个算法想要测试一个对象是否已经在一组100万个对象中,它必须调用Equals
100万次,但只需要调用GetHashCode()
一次(以及几次调用Equals
来消除不同但具有相同哈希码的对象)。
GetHashCode允许您将物品放入桶中-多个对象可以具有相同的哈希码。然后使用Equals在桶内查找匹配项。这使您可以快速在大型集合中查找物品。
GetHashCode()
让你得到一个整数值,可以用于哈希表。这个哈希码是哈希表如此高效的原因之一。然而,可能有多个对象具有相同的哈希码。这就是为什么 Equals()
会被调用。如果这些对象不相等,则它们可以进入同一个桶中;如果它们相等,则已经在哈希表中,无需添加。
GetHashCode
的关键是,两个对象的哈希码不同不仅表明这两个对象不同,而且还表明了更强大的观察结果:如果一个集合中所有项的哈希码具有另一个集合中所有对象所缺少的属性,则这两个集合没有任何公共项。GetHashCode
返回偶数的对象放入一个集合中,将所有 GetHashCode
返回奇数的对象放入另一个集合中,然后给定一个要查找的对象,调用 GetHashCode
将使我们能够立即从其中一个集合中排除所有对象。如果使用了二十个集合,那么就可以排除十九个集合中的所有内容。如果使用 256 个集合,则可以排除 255 个集合中的所有内容。在许多情况下,根据拥有的项目数量调整集合的数量,就可以在不查看 任何 对象的情况下消除除了少数对象之外的所有对象。
GetHashCode
主题的无数相似问题中的一个很好的变体。 - nawfal