为什么使用GetHashCode()而不是Equals()?

时间:2011-06-10 10:53:43

标签: .net performance equals gethashcode

HashSet<T>.Add首先比较GetHashCode的结果。如果它们相同,则会调用Equals

现在,我的理解是为了实现GetHashCode必须使用对象的字段来完成。可以在What is the best algorithm for an overridden System.Object.GetHashCode?找到一个简单的示例实现。

在我的测试中,比较填充了随机数据的1.000.000对对象,两者之间的性能大致相等。 GetHashCode已在链接示例中实施,Equals只需在所有字段上调用Equals即可。那么为什么要使用GetHashCode而不是Equals

5 个答案:

答案 0 :(得分:18)

对于某些类型,Equals测试可能相对昂贵。它通常必须比较类的每个字段。换句话说,它需要类的大小的线性时间。比较平等的更大的类更昂贵。

现在,如果您需要将一个对象与另外一个对象进行比较,会发生什么?调用Equals 1000次可能会变得昂贵。如果N是类的大小

,则需要进行N * 2000字段访问

GetHashCode根据类的内容生成“大多数唯一”整数。换句话说,类字段被访问一次。一旦你有了,你可以将这个整数与构成其他对象的哈希码的1000个整数进行比较。

即使在这种天真的用例中,我们现在只需要N * 1000个字段访问。

但是如果我们存储哈希码呢?当我们将一个对象插入一个哈希集时,它的哈希码计算一次。现在,任何时间我们想要在哈希集中进行查找,我们只需要计算一个哈希码(外部对象的哈希码),然后你就拥有了比较简单的整数。 所以N类字段访问(对于我们需要计算其哈希码的新对象),加上一些整数比较,这些比较因算法而异,但是1)相对较少,而且2)便宜。

答案 1 :(得分:8)

因为如果一个算法想要测试1个对象是否已经在一组1.000.000个对象中,那么它必须调用Equals 1.000.000次,但GetHashCode()只调用一次(和几个)调用Equals以消除虽然具有相同哈希码的不同对象。)

答案 2 :(得分:2)

GetHashCode允许您将事物放入存储桶 - 多个对象可以具有相同的哈希码。然后使用等于在桶中查找匹配。这让你可以很快找到大型藏品中的东西

答案 3 :(得分:1)

GetHashCode()为您提供可用于哈希表的整数值。哈希码是哈希表如此高效的原因之一。但是,可以有多个具有相同哈希码的对象。这就是调用Equals()的原因。如果对象不相等,它们可以进入同一个桶,如果它们相等,那么它已经在哈希表中而不需要添加。

答案 4 :(得分:1)

GetHashCode的基本方面是观察到两个对象的哈希码不同,这不仅构成了对象不同的观察,而且构成了对更强大的东西的观察:如果所有项目的哈希码都是一组具有缺少另一组中所有对象的属性,那么这些组没有共同的项目。

例如,如果将GetHashCode返回偶数的所有对象放入一个集合中,并且将GetHashCode返回奇数的所有对象放入另一个集合中,则给出一个对象寻找,调用GetHashCode将允许人们立即消除其中一个集合中的所有对象。如果不是使用两套,而是使用二十套,一个可以消除十九套中的所有东西。如果256套,一个可以消除255.在许多情况下,如果根据一个项目的数量来调整集合的数量,就可以消除除少数几个对象之外的所有对象而无需查看 any 他们。

查看两个对象的哈希码以查看它们是否相等,很少比直接检查对象的相等性更快。另一方面,无论相等比较多快,无论如何都能够知道一个物体不等于999,990个物体而不看它们,往往要快得多。

相关问题