C#是通用HashSet< T>搜索性能应该是O(1),并且ObservableCollection的搜索性能< T>应该是O(n)。
我有大量的唯一元素,每个元素都有一个不唯一的DateTime属性。
每个元素只需返回其DateTime.GetHashCode()即可计算其HashCode。
现在我想获取我的数据的子集,例如所有元素的日期都在2012年3月到2012年6月之间。
var result = from p in this.Elements
where p.Date >= new DateTime(2012, 03, 01) &&
p.Date <= new DateTime(2012, 30, 06
select p;
如果我在300.000个元素的集合上运行此LINQ查询,则返回给定范围内的80个元素需要大约25毫秒 - 如果我使用HashSet&lt; T&gt;则无关紧要。或ObservableCollection&lt; T&gt;。
如果我手动遍历所有元素并检查它们,则需要相同的时间,~25 ms。
但我知道所有日期的HashCode都在给定的范围内。是否可以从我的HashSet&lt; T&gt;中获取具有给定HashCodes的所有元素?我认为那会更快......
是否可以加快LINQ查询?我假设它没有使用我的HashSet&lt; T&gt;的特殊能力?
答案 0 :(得分:4)
您没有使用正确的数据结构。您应该使用类似排序列表(在Date
属性上排序)的内容,然后您可以二进制搜索范围的开头和结尾。
答案 1 :(得分:4)
正如已经指出的,散列集在确定给定散列是否在集合中非常有效。您的查询只是使用hashset实现IEnumerable迭代整个集合并进行日期比较的事实。它根本不会使用哈希值。这就是手动方式与查询时间相同的原因。
您无法根据散列集中的散列获取元素,您只能测试集合中元素的存在。如果您需要获取字典,则需要字典(看来你没有)
确定您需要对数据执行的操作,并使用针对此进行优化的结构。这可能是您自己的类,它维护多个内部结构,每个内部结构在一件事情上都是有效的(例如,一个用于搜索范围,另一个用于通过多个字段进行检查),或者可能存在符合您需求的现有结构。但是,如果不知道你想要对你的数据做什么,很难提出建议。
要考虑的另一件事是你是否过早优化。如果手动搜索25ms足够快,那么实现IEnumerable的任何结构都可能足够好。在这种情况下,您可以根据您需要的其他标准选择一个。