制作多个字符串的哈希键的最快方法

时间:2013-10-08 14:23:30

标签: c# performance

历史为何很长,但问题很简单。 有3个字符串我需要缓存匹配的值。 要使用快速缓存,我使用以下代码:

public int keygen(string a, string b, string c)
    {
        var x = a + "@@" + b + "@@" + c;
        var hash = x.GetHashCode();
        return hash;
    }

(请注意,字符串abc不包含代码"@@") 它自己的缓存只是Dictionary<int, object>

我知道散列密钥可能不是唯一的,但除此之外:

有没有人知道更快的方法来制作一个int键? (在C#中) 此操作占用总CPU时间的约15%,这是一个长期运行的应用程序。

我尝试了几种实现,但没有找到更快的。

5 个答案:

答案 0 :(得分:4)

您应该使用Dictionary<Tuple<string,string,string>, object>。然后你不必担心非唯一性,因为字典会为你处理它。

答案 1 :(得分:3)

更快的方法是分别计算每个字符串的哈希值,然后使用哈希函数将它们组合起来。这将消除可能需要时间的字符串连接。

e.g。

public int KeyGen(string a, string b, string c)
{
    var aHash = a.GetHashCode();
    var bHash = b.GetHashCode();
    var cHash = c.GetHashCode();
    var hash = 36469;
    unchecked
    {
        hash = hash * 17 + aHash;
        hash = hash * 17 + bHash;
        hash = hash * 17 + cHash;
    }
    return hash;
}

答案 2 :(得分:2)

不是连接字符串(创建新字符串),而是使用XOR或更简单的数学(J.Skeet的信用):

public int keygen(string a, string b, string c)
{
    unchecked // Overflow is fine, just wrap
    {
        int hash = 17;
        hash = hash * 23 + a == null ? 0 : a.GetHashCode();
        hash = hash * 23 + b == null ? 0 : b.GetHashCode();
        hash = hash * 23 + c == null ? 0 : c.GetHashCode();
        return hash;
    }
}

通常,没有必要生成唯一的哈希值。但你应该尽量减少碰撞。

另一种(效率不高)方式是使用内置支持GetHashCode的匿名类型:

public int keygen(string a, string b, string c)
{
    return new { a, b, c }.GetHashCode();
}

请注意,名称,类型和顺序对于计算匿名类型的哈希码很重要。

答案 3 :(得分:1)

  

我知道散列密钥可能是非唯一的风险

哈希键不必是唯一的 - 如果最小化冲突,它们只会更好地工作。

也就是说,计算字符串哈希码所用时间的15%似乎非常高。即使切换到string.Concat()(编译器可能会为你做的事)或StringBuilder也不应该产生那么大的差别。我建议三重检查您的测量结果。

答案 4 :(得分:0)

我猜这个函数的大部分时间都花在构建连接字符串上,只是在它上面调用GetHashCode。我会尝试像

这样的东西
public int keygen(string a, string b, string c)
{
    return a.GetHashCode() ^ b.GetHashCode() ^ c.GetHashCode();
}

或者可能使用比简单的XOR更复杂的东西。但是,请注意GetHashCode 加密哈希函数!它是用于哈希表的哈希函数,而不是用于加密,你绝对不应该将它用于任何与安全相关的密钥(如keygen名称提示)。