我有这个遗留代码,其中通常存在字符串字典到字符串字典到某个对象的模式。
Dictionary<string, Dictionary<string, someobject>>
然后检索对象总是基于两次TryGetValue
Dictionary<string, Dictionary<string, Dealer>> dicDealers ...
if (dicDealers.TryGetValue(lab, out dealers))
dealers.TryGetValue(dealerNumber, out dealer);
现在我认为当两个字符串键组合成一个带有两个字符串成员的键结构时,它应该更有效,这样就可以一次性检索对象。所以我创建了一个Key结构,它覆盖了GetHashCode和Equals计算机器人关键成员的哈希值。
public struct Key<T>
{
private T mKey1;
private T mKey2;
public Key(T t, T u)
{
mKey1 = t;
mKey2 = u;
}
public override bool Equals(object obj)
{
if (obj == null) return false;
Key<T> rhs = (Key<T>)obj;
return mKey1.Equals(rhs.mKey1) && mKey2.Equals(rhs.mKey2);
}
public override int GetHashCode()
{
int hash = 17;
hash = ((hash << 5) - hash) + mKey1.GetHashCode();
hash = ((hash << 5) - hash) + mKey2.GetHashCode();
return hash;
}
}
现在你可以马上做到。
Key<string> key = new Key<string>(lab, dealerNumber);
if (dicDealers.TryGetValue(key, out someobject))
{
...
}
我认为它应该更快但事实证明两种方式都快得多。怎么可能?我能做些什么来让第二种技术运行得更快吗?
答案 0 :(得分:7)
您正在尝试改进已摊销O(1)复杂度的方法。这是一个很高的任务,你永远不会比O(1)更有效 ,没有O(1 / x)的算法。
唯一可以改进的是哦。字典的哦取决于GetHashCode()的成本以及散列代码的分布情况。你再次打一场很难取胜的战斗。 String.GetHashCode()用hand-optimized code编写,产生非常好的哈希值。
实际上你并没有使你的GetHashCode()更高效,它的成本与原始版本中的两个GetHashCode()相同。所以,是的,您当然应该期待您的版本花费尽可能多的时间。
尝试制作更好的版本是一个很长的镜头。你必须对字符串有特殊的了解,比如知道好的哈希只需要第一个字符,这样你就可以在计算整个字符串的哈希值时采用快捷方式。这种情况并不常见,有点危险,糟糕的哈希代码分发是有害的。最重要的是,不是必需的。您犯的核心错误是尝试改进不需要改进的代码。只有在分析器告诉您TryGetValue()是关键代码时才考虑这样做。