现在我使用Dictionary在我的应用程序中存储一些配置数据。数据只被添加到Dictionary一次,但它会得到非常频繁的查询。字典有大约2500个项目,所有“键”都是唯一的。
所以现在我有这样的事情:
private Dictionary<string, string> Data;
public string GetValue(string key) // This gets hit very often
{
string value;
if (this.Data.TryGetValue(key, out value))
{
return value;
}
...
}
有更优化的方法吗?
答案 0 :(得分:2)
你所拥有的是非常有效的。提高性能的唯一方法是使用int
作为字典键,而不是string
。您需要运行性能测试以查看它在您的用例中产生多大影响 - 它可能会也可能不会很重要。
我会使用枚举来存储设置以方便使用。当然,这假设您有一组已知的设置。
private Dictionary<int, string> Data;
public string GetValue(MyAppSettingsEnum key)
{
string value;
if (this.Data.TryGetValue((int)key, out value))
{
return value;
}
...
}
请注意,我不直接使用枚举作为字典键,因为使用int
作为键更有效。有关该问题的更多详情here。
答案 1 :(得分:1)
使用TryGetValue
是返回项目的一种非常优化的方式,因此您无法在此方面进行改进。但是,如果这不会导致瓶颈,我不会过分担心尝试优化TryGetValue
。
你可以做的一件事,但是你的代码中没有显示,所以我不知道你是否是,创建一个具有估计容量的Dictionary
对象。由于您似乎知道将要预期的大量项目,因此创建具有该容量的Dictionary将提高性能,因为它将减少.NET必须调整字典大小的次数。
来自MSDN:
如果可以估计集合的大小,请指定初始值 容量消除了执行大量调整大小的需要 将元素添加到词典时的操作。
答案 2 :(得分:1)
唯一更快的方法是使用数组,如果你的键是int并且范围很短。
答案 3 :(得分:0)
从System.Collections.Generic.Dictionary
的源代码(http://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs提供)中可以看出,您案例中使用的最常用代码是
private int FindEntry(TKey key) {
if( key == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (buckets != null) {
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
}
}
return -1;
}
正如你可以看到的那样,如果comparer.GetHashCode
很快并且产生了很好的哈希码分布,那么查找会很快,如果可能的话perfect hash function。
在您的示例中看不到字典构造代码,但如果使用默认构造函数,则字典将使用默认比较器EqualityComparer<string>.Default
。
为您自己的比较器提供时间和放大器节省空间的哈希函数可以加速代码。
如果您不知道好的哈希函数在您的情况下应该是什么样子,那么使用实习字符串也可能会给您一些提升(参见http://www.dotnetperls.com/string-intern(或MSDN: String.Intern Method))