HashSet性能(与ObservableCollection相比)

本文关键字:相比 ObservableCollection 性能 HashSet | 更新日期: 2023-09-27 18:34:34

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

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

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

(搜索操作似乎非常有效,从 300.000 个元素的未排序集合中查找 80 个随机选择的元素只需 ~30 毫秒(。

每个元素通过简单地返回 DateTime.GetHashCode(( 来实现 GetHashCode(( 方法。

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

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

如果元素具有"良好"的哈希函数(很少有元素具有相同的哈希代码(,那么 HashSet 不是比 ObservableCollection 更强大吗?

HashSet<T>性能(与ObservableCollection<T>相比)

您必须重写对象的 Equals 方法。

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

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。最后一个集合类型通常较慢,因为在每次集合更改(添加、删除、清除、插入等(时,都会触发 PropertyChanged 和 CollectionChanged 事件。

您可以通过

减少更改通知来优化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();

包含源代码的文章:基于 XAML 的应用程序的表示模式。

好吧,马塞尔的回答是正确的,但如果性能真的很重要,你可以稍微改进他的平等方法:

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);
    }
}

使用此方法,您可以避免两次检查对象是否属于特定类型的昂贵函数,只需调用一次并执行快速 null 检查。有关它的更多信息,您可以查看 Eric 的这篇文章。