HashSet <t>性能(与ObservableCollection <t>相比)?</t> </t>

时间:2012-05-17 15:45:39

标签: c# performance observablecollection hashset

我目前正在开展一个项目,我必须管理大量独特元素。每个元素都有~20个属性,每个元素都有一个公共属性DateTime。

属性DateTime不是唯一的,因此我不能使用通用字典来存储我的数据。

目前我将这些元素放入ObservableCollection中,但是从集合中删除元素的性能非常慢,我最终等待~20秒从〜25.000元素的集合中删除~7000个元素。

(搜索操作似乎非常有效,从300,000个元素的未分类集合中找到80个随机选择的元素只需约30毫秒。)

每个元素只需返回DateTime.GetHashCode()即可实现GetHashCode()方法。

我认为使用HashSet而不是ObservableCollection会增加我的性能,但它似乎根本没有效果......

使用通用字典更糟糕......

如果元素具有“良好”的散列函数(很少有元素具有相同的散列码),那么HashSet是否比ObservableCollection更强大???

3 个答案:

答案 0 :(得分:3)

您必须覆盖对象的Equals方法。

因为HashSet使用通常首先检查(null)的内部IEqualityComparer实例,然后使用重写的 Equals将“非null”项与另一项进行比较方法:

class MyObject
{
    public Guid Id { get; set; }

    public override bool Equals(object other)
    {
        if (other is MyObject)
        {
            // use the 'Id' property as identifier

            MyObject myObj = (MyObject)obj;
            return myObj.Id == this.Id;
        }

        // is not a 'MyObject' based object
        return base.Equals(other);
    }
}

您还可以使用与您的对象相当的字符串或任何其他类型的对象。

编辑:

因此,您可以使用HashSet而不是OberservableCollection。最后一个集合类型通常较慢,因为在每个集合更改(添加,删除,清除,插入等)时,PropertyChangedCollectionChanged事件都会被触发。

答案 1 :(得分:2)

您可以通过减少更改通知来优化ObservableCollection的效果。我编写了一个自定义集合类ItemCollection,其中包含更新机制(BeginUpdate / EndUpdate):

  ItemCollection<Customer> customers = new ItemCollection<Customer>
  customers.BeginUpdate();
  customers.Add( new Customer( "Joe", "Smith" ) );
  customers.Add( new Customer( "Mary", "Jones" ) );
  customers.Add( new Customer( "Lisa", "Black" ) );
  customers.Add( new Customer( "Peter", "Brown" ) );
  customers.EndUpdate();

包含源代码的文章:Presentation Patterns for XAML based Applications

答案 2 :(得分:2)

马塞尔的答案是正确的,但如果表现真的很重要,你可以略微改进他的平等方法:

class MyObject
{
    public Guid Id { get; set; }

    public override bool Equals(object other)
    {
        MyObject myObj = obj as MyObject;

        if (myObj != null)
        {
            // use the 'Id' property as identifier
            return myObj.Id == this.Id;
        }

        // is not a 'MyObject' based object
        return base.Equals(other);
    }
}

使用这种方法,您可以避免代价高昂的函数通过仅调用一次并执行快速空检查来检查对象是否属于特定类型两次。有关它的更多信息,您可以查看this article from Eric