11

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

现在,我的理解是为了实现GetHashCode,必须对对象的字段做一些事情。一个简单的示例实现可以在What is the best algorithm for an overridden System.Object.GetHashCode?.

在我的测试中,比较了 1.000.000 对充满随机数据的对象,两者的性能或多或少相等。GetHashCode如链接示例中那样实现,Equals只需调用Equals所有字段。那么为什么要使用GetHashCodeoverEquals呢?

4

5 回答 5

20

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

现在,如果您需要将一个对象与 1000 个其他对象进行比较,会发生什么?调用Equals1000 次可能会很昂贵。如果 N 是类的大小,您需要进行 N*2000 字段访问

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

即使在这样一个幼稚的用例中,我们现在也只需要 N*1000 个字段访问。

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

于 2011-06-10T11:12:19.523 回答
8

因为如果一个算法想要测试一个对象是否已经在一组 1.000.000 个对象中,它必须调用Equals1.000.000 次,但GetHashCode()只调用一次(以及几次调用Equals以消除尽管具有相同哈希但不同的对象代码)。

于 2011-06-10T10:58:06.330 回答
2

GetHashCode 可让您将事物放入桶中 - 多个对象可以具有相同的哈希码。然后使用 Equals 在存储桶中查找匹配项。这让您可以非常快速地找到大型集合中的内容

于 2011-06-10T10:57:55.860 回答
1

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

例如,如果将GetHashCode返回偶数的所有对象放入一个集合,GetHashCode将返回奇数的所有对象放入另一个集合,然后给定一个要查找的对象,调用GetHashCode将允许人们立即排除所有其中一组中的对象。如果不是用两套,一套用了二十套,一个人就能从十九套中消除一切。如果是 256 组,则可以消除 255 组。在许多情况下,如果根据拥有的物品数量调整组的数量,则可以消除除少数对象之外的所有对象,而无需查看任何对象。

查看两个对象的哈希码以查看它们是否相等几乎不会比直接检查对象是否相等更快。另一方面,能够知道一个对象不等于 999,990 个其他对象而不查看它们往往比查看对象快得多,无论相等比较的速度有多快。

于 2013-12-18T05:09:46.380 回答
1

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

于 2011-06-10T10:57:46.857 回答