2

我有一个自定义对象,我们将其称为“MyObject”。它具有三个主要属性,称为 X、Y 和 Z,它们决定了它是否是唯一的。我有一个 HashSet,在 HashSet 中包含 400,000 个“MyObject”。我最初生成唯一哈希码的解决方案既简单又快速。

return Convert.ToInt32(X * 76 + Y * 100 + Z * 23);

但是,由此生成的整数不够唯一。使用当前的 HashCode,这两个点匹配,即使 Y 略有不同。

X:392598.200000000190 Y:4935367.900000000400

X: 392598.200000000190 Y: 4935367.900580000100

我试过的:

double value = (X * 101 + Y * 89 + Z * 56);
return value.GetHashCode();
  • 非常准确,有 1 - 10,000 条记录,只需几秒钟即可计算出差异。然而,有 400,000 条记录,它陷入了困境。我让它运行了 17 个小时,它仍然没有返回我的结果。
  • 转换为字符串,然后获取字符串的哈希码。精确,但无用的缓慢。
  • 增加 X、Y 和 Z 的乘数。生成的数字变得太大。我尝试使用这里使用的方法:http: //msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

    return ((int)value ^ (int)(value >> 32));
    

但是它不再允许整数。我还担心,即使我增加了大小,它可能会像我的其他解决方案一样变得无用缓慢。

如果匹配,我无法进行额外检查,因为 400,000 条记录中有 390,000 条可能匹配

什么是最好的解决方案?或者有没有办法让我的两个已经精确的操作显着更快?我正在考虑从小数点后的值中删除所有零,直到它遇到非零,然后使用我原来的逻辑,即(45.0002030 将变为 45.2030)

4

1 回答 1

4

您可以轻松地从几个对象中计算出合理的哈希码,如下所示:

public override int GetHashCode()
{
    int hash = 17;

    hash = hash * 23 + X.GetHashCode();
    hash = hash * 23 + Y.GetHashCode();
    hash = hash * 23 + Z.GetHashCode();

    return hash;
}

您可以根据需要向其中添加任意数量的哈希码,因为您向类中添加必须对哈希码有贡献的新字段。

这通常是一种快速操作。

另请注意,如果您有不可变类型,则可以通过在不可变类型的构造函数中计算哈希码或通过按需延迟计算(然后缓存结果)来加快速度。

[编辑]

你看到你的代码变慢了,你确定那不是因为你遇到了很多哈希码冲突,而不是哈希码计算本身太慢了吗?

例如,如果您只为每个哈希码返回 0,它会非常快,但一段时间后添加到哈希集合会非常慢。

我希望计算这样的哈希码所花费的时间与实际将项目添加到集合中所花费的时间相形见绌。

[二次编辑]

double.GetHashCode()(通过获得)的实现Reflector是:

public override unsafe int GetHashCode()
{
    double num = this;
    if (num == 0.0)
    {
        return 0;
    }
    long num2 = *((long*) &num);
    return (((int) num2) ^ ((int) (num2 >> 32)));
}

这对我来说看起来很快。

于 2013-06-11T12:58:43.733 回答