什麼是集合(collection)?
什麼是ArrayList?
如何使用ArrayList
View CodeArr重要的方法和屬性
View Code IsSynchronized屬性,ArrayList.Synchronized方法
1-》IsSynchronized屬性指示當前的ArrayList實例是否支持線程同步 2-》而ArrayList.Synchronized靜態方法則會返回一個ArrayList的線程同步的封裝
1-》如果使用非線程同步的實例,那麼在多線程訪問的時候,需要自己手動調用lock來保持線程同步,例如:
ArrayList list = new ArrayList();
//...
lock( list.SyncRoot ) //當ArrayList為非線程包裝的時候,SyncRoot屬性其實就是它自己,但是為了滿足ICollection的SyncRoot定義,這裡還是使用SyncRoot來保持源代碼的規范性
{
list.Add( “Add a Item” );
}
2-》如果使用ArrayList.Synchronized方法返回的實例,那麼就不用考慮線程同步的問題,這個實例本身就是線程安全的,實際上ArrayList內部實現了一個保證線程同步的內部類,ArrayList.Synchronized返回的就是這個類的實例,它裡面的每個屬性都是用了lock關鍵字來保證線程同步。
但是,使用這個方法(ArrayList.Synchronized)並不能保證枚舉的同步,例如,一個線程正在刪除或添加集合項,而另一個線程同時進行枚舉,這時枚舉將會拋出異常。所以,在枚舉的時候,你必須明確使用 SyncRoot 鎖定這個集合。
ArrayList與數組轉換
View CodeArrayList最佳使用建議
這一節我們來討論ArrayList與數組的差別,以及ArrayList的效率問題
(1)ArrayList是Array的復雜版本,ArrayList內部封裝了一個Object類型的數組,從一般的意義來說,它和數組沒有本質的差別,甚至於ArrayList的許多方法,如Index、IndexOf、Contains、Sort等都是在內部數組的基礎上直接調用Array的對應方法。
(2)內部的Object類型的影響對於一般的引用類型來說,這部分的影響不是很大,但是對於值類型來說,往ArrayList裡面添加和修改元素,都會引起裝箱和拆箱的操作,頻繁的操作可能會影響一部分效率。消除這個影響是沒有辦法的,除非你不用它,否則就要承擔一部分的效率損失,不過這部分的損失不會很大。
(3)數組擴容,這是對ArrayList效率影響比較大的一個因素。每當執行Add、AddRange、Insert、InsertRange等添加元素的方法,都會檢查內部數組的容量是否不夠了,如果是,它就會以當前容量的兩倍來重新構建一個數組,將舊元素Copy到新數組中,然後丟棄舊數組,在這個臨界點的擴容操作,應該來說是比較影響效率的。
例1:比如,一個可能有200個元素的數據動態添加到一個以默認16個元素大小創建的ArrayList中,將會經過:
16*2*2*2*2 = 256四次的擴容才會滿足最終的要求,那麼如果一開始就以:ArrayList List = new ArrayList( 210 );的方式創建ArrayList,不僅會減少4次數組創建和Copy的操作,還會減少內存使用。
(4)頻繁的調用IndexOf、Contains等方法(Sort、BinarySearch等方法經過優化,不在此列)引起的效率損失
首先,我們要明確一點,ArrayList是動態數組,它不包括通過Key或者Value快速訪問的算法,所以實際上調用IndexOf、Contains等方法是執行的簡單的循環來查找元素,所以頻繁的調用此類方法並不比你自己寫循環並且稍作優化來的快,如果有這方面的要求,建議使用Hashtable或SortedList等鍵值對的集合。
隊列(Queue)和棧(Stack):
System.Collections.Stack 和 System.Collections.Queue 類,兩者僅僅實現了ICollection 接口,按照存儲項目加到集合的順序保存System.Object類型的項目。對象只能按其加入順序從集合中檢索:堆棧是後進先出,而隊列則是先進先出。通常情況下,你在以下場合可以考慮采用以上這些集合:
* 接收和處理集合內項目時順序比較重要。
* 你能在處理項目之後丟棄它。
* 你不需要訪問集合中的任意項目。
HashTable:
System.Collections.HashTable集合實現了IDictionary 和 Icollection,能用來存儲多種類型的對象連同關聯的唯一字符串鍵值。在HashTable集合中的項目按照源自其鍵值的哈希代碼所確定的順序存儲。集合內每個對象的鍵值都必須唯一,而其哈希代碼則不一定唯一。
什麼是哈希代碼?哈希代碼實質上就是從一塊數據中消除所有冗余部分之後的結果,它主要起到對數據輔助分類或排序的作用。當某個項目加入集合時,HashTable即調用鍵值的GetHashCode方法,由於所有的類都是從 System.Objec繼承的,所以調用該方法即可確定該類的哈希代碼並且按該代碼排序存儲。你可以強迫使用定制的哈希函數,方法有二,一是重載類的 GetHashCode方法,二是向 HashTable構造器傳遞實現了System.Collections.IHashcodeProvider接口的對象,在這種情況下,該對象將用於為所有加入集合的鍵值產生哈希代碼。
從性能的角度看,因為鍵值搜索僅限於具有同樣哈希代碼的鍵值,所以HashTable能夠很快地從集合中檢索任意一個元素,從而減少了必須通過檢查以發現匹配的鍵值的數量。然而,因為插入到集合中的每個對象-鍵值對都必須產生相應的哈希代碼,所以項目插入的代價就有點高了。因此,HashTable 主要運用在按照任意鍵值反復檢索大量相對靜態的數據這一場合下
Add方法參數都是object類型
對哈希表進行排序
對哈希表進行排序在這裡的定義是對key/value鍵值對中的key按一定規則重新排列,但是實際上這個定義是不能實現的,因為我們無法直接在 Hashtable進行對key進行重新排列,如果需要Hashtable提供某種規則的輸出,可以采用一種變通的做法:
NameValueCollection:
System.Collections.Specialized.NameValueCollection 最有趣的地方在於它能包含關聯同一鍵值的多個項目(允許出現相同的鍵,值會用逗號連起來),這正是它與其他內建集合的差別所在。除此以外,它在功能上類似HashTable,按照源自每一項目鍵值的哈希代碼對項目排序從而也具有類同的優缺點。用處:寫自定義控件存儲鍵值一般用這個
ListDictionary 和 HybridDictionary:
ListDictionary 和 HybridDictionary 類歸屬於System.Collections.Specialized。它們都在按照唯一鍵值的原則來組織項目,而且都實現了 IDictionary 和 ICollection 。ListDictionary在內部以鏈表的方式存儲項目,建議用在不會增長超過10個項目的集合中。HybridDictionary采用一個內部鏈 表(實際上就是ListDictionary)作為小集合,當集合變得足夠大(超過10個項目)以至於鏈表實現效率降低時就會轉換為HashTable。
StringCollection 和 StringDictionary:
System.Collections.Specialized.StringCollection 和 System.Collections.Specialized.StringDictionary 都對存儲字符串的集合進行了優化。 StringCollection實現了 IList 和 ICollection 而且實質上就是ArrayList,只不過實現了強烈的類型化僅僅接受字符串而已。StringCollection最理想的應用場合是經常更新或增加的 少量數據,而StringDictionary則最適用於不經常增加項目到諸如HashTable之類集合中的大量數據。
SortedList:
System.Collections.SortedList,它實現了IDictionary和ICollection接口,是最基本的排序集 合,與Vb6下的Collection對象非常類似。 SortedList存儲對象並按照關聯的鍵值對這些存儲對象排序。它們也是同時支持索引數字和鍵對象檢索的唯一內建的.NET集合,與哈希表類似,區別在於SortedList中的Key數組排好序的
View Code泛型最常見的用途是泛型集合,命名空間System.Collections.Generic 中包含了一些基於泛型的集合類,使用泛型集合類可以提供更高的類型安全性,還有更高的性能,避免了非泛型集合的重復的裝箱和拆箱。