0

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

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

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

我知道哈希键可能是非唯一的,但除此之外:

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

我已经尝试了几个实现,但没有找到更快的方法。

4

5 回答 5

4

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

于 2013-10-08T14:29:27.620 回答
3

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

例如

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;
}
于 2013-10-08T14:25:24.347 回答
3

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();
}

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

于 2013-10-08T14:29:30.997 回答
1

我知道哈希键可能是非唯一的

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

也就是说,你 15% 的时间花在计算字符串的哈希码上似乎非常高。甚至切换到string.Concat()(编译器可能会为你做任何事情)或者StringBuilder不应该有太大的不同。我建议对您的测量结果进行三次检查。

于 2013-10-08T14:25:52.380 回答
0

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

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

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

于 2013-10-08T14:30:13.633 回答