复杂对象图的快速哈希码

4

我有一个相当复杂的对象,需要获取这些对象的唯一性。其中一种解决方案可以通过重写GetHashCode()来实现。我已经实现了以下代码:

public override int GetHashCode()
{
    return this._complexObject1.GetHashCode() ^
           this._complexObject2.GetHashCode() ^
           this._complexObject3.GetHashCode() ^
           this._complexObject4.GetHashCode() ^
           this._complexObject5.GetHashCode() ^
           this._complexObject6.GetHashCode() ^
           this._complexObject7.GetHashCode() ^
           this._complexObject8.GetHashCode();
}

这些复杂的对象还覆盖了 GetHashCode() 并执行类似的操作。
我的项目需要处理这些对象,我需要它们是唯一的,并且数据也会在不同的地方以各种方式发生变化。
我需要一种更快的方法来查找这些复杂对象的唯一性,需要考虑性能和内存。
提前感谢
Munim

2
如果数据是可变的,那么GetHashCode()可能不是一个好的开始 - 除此之外,它只能保证不相等(不能用于测试相等性)。 - Marc Gravell
谢谢Marc,我不是在执行测试相等性,而是使用GetHashCode()来检查对象是否不相等,这正是我需要做的。 - Abdul Munim
只是想确认一下。虽然我不确定是否有一个魔法棒答案。你可能可以通过缓存值并在更改发生时删除缓存的值来做些什么,但在复杂的图形中这很棘手(因为你需要检查所有子对象)。 - Marc Gravell
1个回答

10

根据您的评论,听起来您可能试图仅依靠GetHashCode来确定唯一性。不要这样做。哈希并不打算是唯一的,它只是意味着两个不相等的对象哈希为相同值的可能性很小,但不是不可能的。如果您想检查一组对象是否有重复,您必须同时使用Equals。

请注意,对于哈希码而言,使用异或运算符可能会增加哈希冲突的可能性,具体取决于涉及的各个哈希值。特别地,它会使任何两个相等的字段“互相抵消掉”。我通常使用以下形式:

int hash = 17;
hash = hash * 31 + field1.GetHashCode();
hash = hash * 31 + field2.GetHashCode();
hash = hash * 31 + field3.GetHashCode();
hash = hash * 31 + field4.GetHashCode();
...
return hash;

即使如此,这并不能保证唯一性。你应该使用GetHashCode()来排除相等性,然后使用Equals来检查任何可能相等的值的实际相等性。

现在你的问题提到了速度——这听起来是使用分析器和一些基准测试的完美场所。你确定这是瓶颈吗?如果有许多不同类型计算哈希值,您是否已经找到了其中哪个是问题的最大贡献者?

一些优化将取决于您如何使用数据。如果您发现大部分时间都花费在为您知道没有更改的值重新计算哈希值上,您可以缓存哈希码...尽管当有字段本身引用复杂对象时,这显然变得更加棘手。如果那些叶节点不经常更改(但它们的使用可能会变化),则有可能缓存“叶节点”哈希。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接