James Michael Hare 有一篇 C# 基礎文章:Choosing the Right Collection Class,整理了一些 .NET 集合類別的特性和適用時機,很值得參考。我嘗試用 if-then-else 語法寫了一個協助挑選集合類別的決策邏輯,也許將來碰到不知該選誰的時候可以派上用場。
[2018-02-12 更新]這裡有圖文版小抄: http://www.huanlintalk.com/2018/02/choosing-net-collection-types.html
程式碼如下:
另外要注意的是,所謂的自動排序,指的是元素插入集合或從集合中刪除時,順序會自動重排。但這個重新排序的動作能否 work,主要是看存入集合的元素的類別是否有實作「比較元素的方法或介面」,例如 IComparable 介面。如果元素的型別是 string、int 等基礎型別,當然就沒問題,因為它們已經具備同類型物件互相比大小的功能。如果元素的型別是你自己定義的,例如 Employee、Student,你就得自行實作這些比較的方法。
字典集合(key-value pair)也有類似情形需要注意。字典集合是利用雜湊 (hash) 的方式來把物件存入多個小籃子裡面,而將來搜尋物件時,便利用雜湊值來快速找到物件所在的籃子(位置)。因此,你的自訂類別應該要改寫 GetHashCode() 和 Equals() 方法,才能讓這個雜湊機制有效運作。
對於需要執行緒安全的場合,亦即有多條執行緒會同時讀取和寫入同一個集合物件的元素,這裡就偷懶一下,沒有把挑選的邏輯寫出來,需要的朋友可參考原文。
[2018-02-12 更新]這裡有圖文版小抄: http://www.huanlintalk.com/2018/02/choosing-net-collection-types.html
程式碼如下:
string ChooseCollectionClass()
{
if (不需要執行緒安全 || 只需要對集合進行讀取動作)
{
UsingNamespace("System.Collection.Generic");
if (儲存的資料是 key-value 形式)
{
if (必須自動排序好)
{
if (搜尋、新增、刪除元素的動作都要很快)
{
return "SortedDictionary<TKey, TValue>";
}
else // 以搜尋為主,極少執行插入和刪除元素的動作
{
return "SortedList<TKey, TValue>";
// SortedList 的搜尋速度很快,插入和刪除的速度比較慢.
}
}
else // 元素不用排序
{
return "Dictionary<TKey,TVale>";
}
}
else // 儲存的資料不是 key-value 形式.
{
if (元素在集合中必須是唯一,即不可重複)
{
if (需要自動排序好)
{
return "SortedSet<T>";
}
else
{
return "HashSet<T>";
}
}
else if (必須要像陣列那樣,能夠用索引來存取元素)
{
if (需要自動排序好)
{
return "SortedList<T>";
}
else
{
return "List<T>";
}
}
else // 不需要使用索引來存取元素
{
if (存取元素的順序固定為先進先出)
{
return "Queue<T>";
}
if (存取元素的順序固定為後進先出)
{
return "Stack<T>";
}
if (需要頻繁且大量地插入和刪除元素)
{
return "LinkedList<T>";
}
return "沒有你想要的!";
}
}
}
else // 需要執行緒安全
{
return ChooseFromNamespace("System.Collection.Concurrent");
}
}
另外要注意的是,所謂的自動排序,指的是元素插入集合或從集合中刪除時,順序會自動重排。但這個重新排序的動作能否 work,主要是看存入集合的元素的類別是否有實作「比較元素的方法或介面」,例如 IComparable
字典集合(key-value pair)也有類似情形需要注意。字典集合是利用雜湊 (hash) 的方式來把物件存入多個小籃子裡面,而將來搜尋物件時,便利用雜湊值來快速找到物件所在的籃子(位置)。因此,你的自訂類別應該要改寫 GetHashCode() 和 Equals() 方法,才能讓這個雜湊機制有效運作。
對於需要執行緒安全的場合,亦即有多條執行緒會同時讀取和寫入同一個集合物件的元素,這裡就偷懶一下,沒有把挑選的邏輯寫出來,需要的朋友可參考原文。
沒有留言: