历史为何很长,但问题很简单。 有3个字符串我需要缓存匹配的值。 要使用快速缓存,我使用以下代码:
public int keygen(string a, string b, string c)
{
var x = a + "@@" + b + "@@" + c;
var hash = x.GetHashCode();
return hash;
}
(请注意,字符串a
,b
,c
不包含代码"@@"
)
它自己的缓存只是Dictionary<int, object>
我知道散列密钥可能不是唯一的,但除此之外:
有没有人知道更快的方法来制作一个int键? (在C#中) 此操作占用总CPU时间的约15%,这是一个长期运行的应用程序。
我尝试了几种实现,但没有找到更快的。
答案 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
名称提示)。