Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# HashSet<;T>;性能(与可观察到的采集相比<;T>;)?_C#_Performance_Observablecollection_Hashset - Fatal编程技术网

C# HashSet<;T>;性能(与可观察到的采集相比<;T>;)?

C# HashSet<;T>;性能(与可观察到的采集相比<;T>;)?,c#,performance,observablecollection,hashset,C#,Performance,Observablecollection,Hashset,我目前正在从事一个项目,我必须管理大量独特的元素。每个元素大约有20个属性,每个元素都有一个公共属性DateTime 属性DateTime不是唯一的,因此我无法使用通用字典存储数据 目前,我将这些元素放入了ObservableCollection中,但是从集合中删除元素的性能非常慢,我最终等待了约20秒才能从约25000个元素的集合中删除约7000个元素 (搜索操作似乎相当有效,只需约30 ms即可从300.000个未排序的元素集合中找到80个随机选择的元素) 每个元素通过简单地返回DateTi

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

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

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

(搜索操作似乎相当有效,只需约30 ms即可从300.000个未排序的元素集合中找到80个随机选择的元素)

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

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

使用通用字典更糟糕

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

您必须重写对象的方法

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

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);
    }
}
您还可以使用字符串或任何其他与您的对象类似的对象

编辑:


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

您可以通过减少更改通知来优化
ObservableCollection
的性能。我已经编写了一个自定义集合类,
ItemCollection
,它具有更新机制(
BeginUpdate
/
EndUpdate
):

ItemCollection客户=新建ItemCollection
customers.BeginUpdate();
添加(新客户(“乔”、“史密斯”);
添加(新客户(“玛丽”、“琼斯”);
添加(新客户(“Lisa”、“Black”);
添加(新客户(“彼得”、“布朗”);
customers.EndUpdate();

文章源代码:。

马塞尔的答案是正确的,但如果性能真的很重要,您可以稍微改进他的方法:

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

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

但是,如果DateTime属性不是唯一的(根据帖子),为什么要使用该非唯一属性的GetHashCode()?ObservableCollection和HashSet的作用不同。您开始使用ObservableCollection的原因是什么?您是否将其绑定到WPF或Silverlight控件?HashSet为基本操作(添加、删除、包含和大小)提供恒定的时间性能。@Tigran,因为HashSet不是字典?hashset中的所有项都是唯一的,哈希代码不是唯一的,因此.net使用hashcode作为起始值放置和搜索一个项。GetHashCode()不能保证唯一性,它作为散列键在散列集中均匀分布项。您是否“观察”了ObservableCollection?您的“obvserver”代码可能是性能问题的原因吗?当您删除时,我会被呼叫。如果删除项目很慢,您是否可以将项目标记为已删除,而只添加到可观察的集合中?您可能可以在集合中使用元组而不是元素,只要元组使用两个元素的哈希,并且始终按元组搜索,那么您就不应该匹配已删除的元组,因为它的哈希将发生更改,即使它位于同一个bucket中。当然,这意味着您的收藏将不断增长,最终性能将下降。。。
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);
    }
}