C#HashSet <t>搜索性能(与ObservableCollection <t>相比)?</t> </t>

时间:2012-05-17 16:41:11

标签: performance linq observablecollection hashset

C#是通用HashSet&lt; T&gt;搜索性能应该是O(1),并且ObservableCollection的搜索性能&lt; T&gt;应该是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;的特殊能力?

2 个答案:

答案 0 :(得分:4)

您没有使用正确的数据结构。您应该使用类似排序列表(在Date属性上排序)的内容,然后您可以二进制搜索范围的开头和结尾。

答案 1 :(得分:4)

正如已经指出的,散列集在确定给定散列是否在集合中非常有效。您的查询只是使用hashset实现IEnumerable迭代整个集合并进行日期比较的事实。它根本不会使用哈希值。这就是手动方式与查询时间相同的原因。

您无法根据散列集中的散列获取元素,您只能测试集合中元素的存在。如果您需要获取字典,则需要字典(看来你没有)

确定您需要对数据执行的操作,并使用针对此进行优化的结构。这可能是您自己的类,它维护多个内部结构,每个内部结构在一件事情上都是有效的(例如,一个用于搜索范围,另一个用于通过多个字段进行检查),或者可能存在符合您需求的现有结构。但是,如果不知道你想要对你的数据做什么,很难提出建议。

要考虑的另一件事是你是否过早优化。如果手动搜索25ms足够快,那么实现IEnumerable的任何结构都可能足够好。在这种情况下,您可以根据您需要的其他标准选择一个。