Performance C#HashSet<;T>;搜索性能(与ObservableCollection<;T>;相比)?

Performance C#HashSet<;T>;搜索性能(与ObservableCollection<;T>;相比)?,performance,linq,observablecollection,hashset,Performance,Linq,Observablecollection,Hashset,C#泛型哈希集搜索性能应为O(1),而ObservableCollection的搜索性能应为O(n) 我有大量的唯一元素,每个元素都有一个不唯一的DateTime属性 每个元素只需返回其DateTime.GetHashCode()即可计算其HashCode 现在,我想获取数据的子集,例如,日期在2012年3月至2012年6月之间的所有元素 var result = from p in this.Elements where p.Date >= ne

C#泛型哈希集搜索性能应为O(1),而ObservableCollection的搜索性能应为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;
var result=来自此.Elements中的p
其中p.Date>=新日期时间(2012,03,01)&&

p、 日期您使用的数据结构不正确。您应该使用类似排序列表(按
Date
属性排序)的方法,然后在其中对范围的开始和结束进行二进制搜索。

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

无法根据哈希集的哈希值获取元素,只能测试该元素在该集中的存在性。如果需要通过has获取字典,则需要字典(似乎不需要)

决定您需要对数据做什么,并使用为此而优化的结构。这可能是您自己的类,它维护多个内部结构,每个结构在一件事情上都是有效的(比如一个用于搜索范围,另一个用于通过多个字段检查是否存在),或者可能存在一个适合您需要的现有结构。但是,如果不知道您想对数据做什么,就很难给出建议


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

每个元素的哈希代码是否都是其日期?哈希集没有特殊功能,可以有效检索日期在某个范围内的元素。哈希集允许快速确定特定对象或值是否在该集中。我的第一个观察结果是,如果对象不同,哈希代码应尽可能不同(显然,情况并非总是如此,但这正是您应该追求的目标)。就你而言,情况并非如此。不同的元素具有相同的哈希代码,这是不好的。在最坏的情况下,如果您只有三个不同的唯一日期,那么您的hashset将只有三个bucket,因此在hashset中查找某些内容将必须对该bucket中的所有元素进行排序,从而使其成为O(n)(给定或获取)。我还应该注意到,这是一个一般性的注释,与ques没有直接关系:)哦,作为一个附加注释,您所说的hashset是this.elements吗?问题还不清楚……如果你有300000个元素,你是从数据库中提取它们的吗?如果是这样,您只能获取正确日期范围内的项目,这应该会快得多。是的,我肯定会使用SortedList或SortedDicionary,但我不能-元素的“日期”不是唯一键…@ehssand为什么日期不唯一会阻止您使用字典?只要Equals方法正确地确定了两个实例何时相等,并且gethashcode始终为两个不同的对象返回相同的值,如果这些对象之间的Equals也是真的,那么它就可以工作。@SamHolder我不确定我是否正确理解您所说的内容,但是,如果我想使用字典按日期高效地搜索元素,字典的键应该是该日期,对吗?但在我的收藏中,很少有日期不是独一无二的。。。“所以我不能把它们当钥匙用?”埃桑多是的,对不起,我理解失败了。我忘了你只有一个日期,没有完整的对象。虽然正如Jason所建议的那样,排序列表应该是好的,因为一个列表可以有多个具有相同键的元素。因此,找到第一个元素的索引和您想要的日期,然后找到元素的索引和最后一个日期,然后得到这些索引之间的所有元素。谢谢您的回答。我认为,目前的搜索性能已经足够了,我只是认为可以通过哈希代码直接检索元素,正如您所指出的,这是不可能的。
HashSet
的Remove方法比任何“普通”集合提供的方法性能更好,因此我肯定会使用HashSet。