2012-05-17 75 views
3

我目前正在開發一個項目,我必須管理大量獨特元素。每個元素都有〜20個屬性,每個元素都有一個公共屬性DateTime。HashSet <T>性能(與ObservableCollection <T>相比)?

屬性DateTime不是唯一的,所以我不能使用通用字典來存儲我的數據。

目前我將這些元素放入ObservableCollection中,但從集合中移除元素的性能非常慢,我最終等待~20秒鐘以從〜25.000個元素的集合中移除〜7000個元素。

(搜索操作似乎非常有效,從300,000個元素的未分類集合中找到80個隨機選擇的元素只需要約30 ms)。

每個元素通過簡單地返回DateTime.GetHashCode()來實現GetHashCode()方法。

我想到用一個HashSet,而不是一個ObservableCollection會增加我的表現頗有幾分,但似乎並未有根本的影響...

,並使用通用字典更是雪上加霜。 ..

如果元素具有「良好」的散列函數(有很少的元素具有相同的散列碼),那麼HashSet是不是比ObservableCollection更強大?

+0

'HashSet '也必須是唯一的。 – SLaks

+1

但是,如果DateTime屬性是* not * unique(根據帖子),爲什麼您使用該非獨特屬性的GetHashCode()? – Tigran

+1

ObservableCollection和HashSet不能達到相同的目的。你開始使用ObservableCollection的原因是什麼?你是否將它綁定到WPF或Silverlight控件? HashSet爲基本操作(添加,刪除,包含和大小)提供恆定的時間性能。 – Martin

回答

3

您必須重寫對象的Equals方法。

由於HashSet使用內部IEqualityComparer實例爲(空)通常首先檢查,然後通過使用該重寫與另一項目「非空」項進行比較的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); 
    } 
} 

您也可以使用字符串或任何其他類型的對象與您的對象相媲美。

編輯:

所以,你可以用它代替OberservableCollection HashSet中。最後一個集合類型通常會比較慢,因爲每次集合更改(添加,刪除,清除,插入等)時會觸發PropertyChangedCollectionChanged事件。

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

那麼馬塞爾的答案是正確的,但如果表現真的很重要,你可以稍微改善自己的equals方法:

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

用這種方法你避免昂貴功能檢查,如果一個對象是specifc型兩次只需調用一次,然後執行快速空檢查。欲瞭解更多關於它的信息,你可以看看this article from Eric

相關問題