我是不是用错了字典,好像太慢了
本文关键字:是不是 错了 字典 | 更新日期: 2023-09-27 18:01:45
我已经使用了VS profiler,并且注意到程序大约40%的时间花在下面的行中。我使用title1
和color1
,因为Visual Studio或Resharper建议这样做。下面的代码有任何性能问题吗?
Dictionary<Item, int> price_cache = new Dictionary<Item, int>();
....
string title1 = title;
string color1 = color;
if (price_cache.Keys.Any(item => item.Title == title && item.Color == color))
{
price = price_cache[price_cache.Keys.First(item => item.Title == title11 && item.Color == color1)];
问题是您的Keys.Any
方法遍历字典中的所有键以查找是否有匹配。之后,使用First
方法再次执行相同的操作。
Dictionary适用于已经拥有键并希望快速获取值的操作。在这种情况下,它将计算您的密钥(在您的情况下为Item
)的哈希码,并使用它"跳转"到存储项的桶。
首先,您需要创建自定义比较器,让Dictionary
知道如何比较项目。
class TitleColorEqualityComparer : IEqualityComparer<Item>
{
public bool Equals(Item a, Item b)
{
// you might also check for nulls here
return a.Title == b.Title &&
a.Color == b.Color;
}
public int GetHashCode(Item obj)
{
// this should be as much unique as possible,
// but not too complicated to calculate
int hash = 17;
hash = hash * 31 + obj.Title.GetHashCode();
hash = hash * 31 + obj.Color.GetHashCode();
return hash;
}
}
然后,使用自定义比较器实例化字典:
Dictionary<Item, int> price_cache =
new Dictionary<Item, int>(new TitleColorEqualityComparer());
从这里开始,您可以简单地写:
Item some_item = GetSomeItem();
price_cache[some_item] = 5; // to quickly set or change a value
或者,搜索字典:
Item item = GetSomeItem();
int price = 0;
if (price_cache.TryGetValue(item, out price))
{
// we got the price
}
else
{
// there is no such key in the dictionary
}
[编辑]
并且再次强调:永远不要迭代Keys
属性来查找键。如果您这样做,您根本不需要Dictionary
,您可以简单地使用列表并获得相同(甚至稍微更好的性能)。
尝试使用IEqualityComparer,如此页面的示例代码所示:http://msdn.microsoft.com/en-us/library/ms132151.aspx,并使其根据标题和颜色计算哈希码。
正如Jesus Ramos所建议的那样(当他说使用不同的数据结构时),您可以将键设置为一个由标题和颜色连接而成的字符串,然后连接搜索字符串并查找该字符串。它应该更快。
所以一个键可以看起来像name1:FFFFFF
(名称,冒号,然后十六进制的颜色),然后你只需格式化搜索字符串的相同方式
将price_cache.Keys.Any()
替换为price_cache.Keys.SingleOrDefault()
,这样就可以将结果存储在变量中,检查是否为空,如果不是,则已经有搜索项,而不是像这里那样搜索两次。
如果你想快速访问你的哈希表,你需要实现GetHashCode和Equals功能:
public class Item
{
.....
public override int GetHashCode()
{
return (this.color.GetHashCode() + this.title.GetHashCode())/2;
}
public override bool Equals(object o)
{
if (this == o) return true;
var item = o as Item;
return (item != null) && (item.color == color) && (item.title== title) ;
}
访问你的字典:
Item item = ...// create sample item
int price = 0;
price_cache.ContainsKey(item);
price_cache[item];
price_cache.TryGetValue(item, out price);