C#集合大全 數組 類 泛型 <轉>


總結C# 集合類 Array Arraylist List Hashtable Dictionary Stack Queue 

 

 我們用的比較多的非泛型集合類主要有 ArrayList類 和 HashTable類。我們經常用HashTable 來存儲將要寫入到數據庫或者返回的信息,在這之間要不斷的進行類型的轉化,增加了系統裝箱和拆箱的負擔,如果我們操縱的數據類型相對確定的化 用Dictionary<TKey,TValue> 集合類來存儲數據就方便多了,例如我們需要在電子商務網站中存儲用戶的購物車信息(商品名,對應的商品個數)時,完全可以用 Dictionary<string, int> 來存儲購物車信息,而不需要任何的類型轉化。

 

1.數組是固定大小的,不能伸縮。雖然System.Array.Resize這個泛型方法可以重置數組大小, 

但是該方法是重新創建新設置大小的數組,用的是舊數組的元素初始化。隨后以前的數組就廢棄!而集合卻是可變長的 

2.數組要聲明元素的類型,集合類的元素類型卻是object. 

3.數組可讀可寫不能聲明只讀數組。集合類可以提供ReadOnly方法以只讀方式使用集合。 

4.數組要有整數下標才能訪問特定的元素,然而很多時候這樣的下標並不是很有用。集合也是數據列表卻不使用下標訪問。 

很多時候集合有定制的下標類型,對於隊列和棧根本就不支持下標訪問! 

 

1.       數組 

int[] intArray1; 

//初始化已聲明的一維數組 

intArray1 = new int[3]; 

intArray1 = new int[3]{1,2,3}; 

intArray1 = new int[]{1,2,3}; 

 

2.       ArrayList類對象被設計成為一個動態數組類型,其容量會隨着需要而適當的擴充 

方法 

1:Add()向數組中添加一個元素, 

2:Remove()刪除數組中的一個元素 

3:RemoveAt(int i)刪除數組中索引值為i的元素 

4:Reverse()反轉數組的元素 

5:Sort()以從小到大的順序排列數組的元素 

6:Clone()復制一個數組 

System.Collections 命名空間包含接口和類,這些接口和類定義各種對象(如列表、隊列、位數組、哈希表和字典)的集合。
System.Collections.Generic 命名空間包含定義泛型集合的接口和類,泛型集合允許用戶創建強類型集合,它能提供比非泛型強類型集合更好的類型安全性和性能。
System.Collections.Specialized 命名空間包含專用的和強類型的集合,例如,鏈接的列表詞典、位向量以及只包含字符串的集合。

ArrayList 類:使用大小可按需動態增加的數組。

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace ConsoleApplication1
{
    class Program
   {
       static void Main(string[] args)
        {
            ArrayList al = new ArrayList();
            al.Add(100);//單個添加
           foreach (int number in new int[6] { 9, 3, 7, 2, 4, 8 })
           {
                al.Add(number);//集體添加方法一
           }
           int[] number2 = new int[2] { 11, 12 };
           al.AddRange(number2);//集體添加方法二
           al.Remove(3);//移除值為3的
           al.RemoveAt(3);//移除第3個
          ArrayList al2 = new ArrayList(al.GetRange(1, 3));//新ArrayList只取舊ArrayList一部份


           Console.WriteLine("遍歷方法一:");
            foreach (int i in al)//不要強制轉換
           {
               Console.WriteLine(i);//遍歷方法一
           }

            Console.WriteLine("遍歷方法二:");
            for (int i = 0; i < al2.Count; i++)//數組是length
            {
               int number = (int)al2[i];//一定要強制轉換
               Console.WriteLine(number);//遍歷方法二

           }
       }
   }
}


 

3.       List 

可通過索引訪問的對象的強類型列表。提供用於對列表進行搜索、排序和操作的方法,在決定使用 List 還是使用 ArrayList 類(兩者具有類似的功能)時,記住 List 類在大多數情況下執行得更好並且是類型安全的。如果對 List 類的類型 T 使用引用類型,則兩個類的行為是完全相同的。但是,如果對類型 T 使用值類型,則需要考慮實現和裝箱問題。 

如果對類型 T 使用值類型,則編譯器將特別針對該值類型生成 List 類的實現。這意味着不必對 List 對象的列表元素進行裝箱就可以使用該元素,並且在創建大約 500 個列表元素之后,不對列表元素裝箱所節省的內存將大於生成該類實現所使用的內存。 

//聲明一個List對象,只加入string參數 

List<string> names = new List<string>(); 

names.Add("喬峰"); 

names.Add("歐陽峰"); 

names.Add("馬蜂"); 

//遍歷List 

foreach (string name in names) 

Console.WriteLine(name); 

//向List中插入元素 

names.Insert(2, "張三峰"); 

//移除指定元素 

names.Remove("馬蜂"); 

 

4.       Dictionary 

 

 

  泛型最常見的用途是泛型集合,命名空間System.Collections.Generic 中包含了一些基於泛型的集合類,使用泛型集合類可以提供更高的類型安全性,還有更高的性能,避免了非泛型集合的重復的裝箱和拆箱。 
    很多非泛型集合類都有對應的泛型集合類,下面是常用的非泛型集合類以及對應的泛型集合類:

非泛型集合類

泛型集合類

ArrayList

List<T>

HashTable

DIctionary<T>

Queue

Queue<T>

Stack

Stack<T>

SortedList

SortedList<T>


    我們用的比較多的非泛型集合類主要有 ArrayList類 和 HashTable類。我們經常用HashTable 來存儲將要寫入到數據庫或者返回的信息,在這之間要不斷的進行類型的轉化,增加了系統裝箱和拆箱的負擔,如果我們操縱的數據類型相對確定的化  用 Dictionary<TKey,TValue> 集合類來存儲數據就方便多了,例如我們需要在電子商務網站中存儲用戶的購物車信息( 商品名,對應的商品個數)時,完全可以用 Dictionary<string, int> 來存儲購物車信息,而不需要任何的類型轉化。

    下面是簡單的例子,包括聲明,填充鍵值對,移除鍵值對,遍歷鍵值對

    Dictionary<string, string> myDic = new Dictionary<string, string>();
    myDic.Add("aaa", "111");
    myDic.Add("bbb", "222");
    myDic.Add("ccc", "333");
    myDic.Add("ddd", "444");
    //如果添加已經存在的鍵,add方法會拋出異常
    try
   {
       myDic.Add("ddd","ddd");
   }
    catch (ArgumentException ex)
   {
       Console.WriteLine("此鍵已經存在:" + ex.Message);
    }
  //解決add()異常的方法是用ContainsKey()方法來判斷鍵是否存在
  if (!myDic.ContainsKey("ddd"))
  {
       myDic.Add("ddd", "ddd");
    }
   else
   {
       Console.WriteLine("此鍵已經存在:");
   
   }

    //而使用索引器來負值時,如果建已經存在,就會修改已有的鍵的鍵值,而不會拋出異常
   myDic ["ddd"]="ddd";
    myDic["eee"] = "555";
   
   //使用索引器來取值時,如果鍵不存在就會引發異常
    try
   {
       Console.WriteLine("不存在的鍵\"fff\"的鍵值為:" + myDic["fff"]);
   }
   catch (KeyNotFoundException ex)
    {
       Console.WriteLine("沒有找到鍵引發異常:" + ex.Message);
    }
   //解決上面的異常的方法是使用ContarnsKey() 來判斷時候存在鍵,如果經常要取健值得化最好用 TryGetValue方法來獲取集合中的對應鍵值
   string value = "";
   if (myDic.TryGetValue("fff", out value))
    {
        Console.WriteLine("不存在的鍵\"fff\"的鍵值為:" + value );
   }
    else
    {     
        Console.WriteLine("沒有找到對應鍵的鍵值"); 
    }
   
   //下面用foreach 來遍歷鍵值對
    //泛型結構體 用來存儲健值對
    foreach (KeyValuePair<string, string> kvp in myDic)
    {
        Console.WriteLine("key={0},value={1}", kvp.Key, kvp.Value);
   }
    //獲取值得集合
    foreach (string s in myDic.Values)
   {
        Console.WriteLine("value={0}", s);
    }
    //獲取值得另一種方式
    Dictionary<string, string>.ValueCollection values = myDic.Values;
   foreach (string s in values)
   {
       Console.WriteLine("value={0}", s);
    }


常用的屬性和方法如下: 

 

 

常用屬性

屬性說明

 

Comparer 

獲取用於確定字典中的鍵是否相等的 IEqualityComparer。 

 

Count 

獲取包含在 Dictionary 中的鍵/值對的數目。

 

Item 

獲取或設置與指定的鍵相關聯的值。

 

Keys 

獲取包含 Dictionary 中的鍵的集合。

 

Values 

獲取包含 Dictionary 中的值的集合。

 

常用的方法

方法說明 

 

Add 

將指定的鍵和值添加到字典中。 

 

Clear 

從 Dictionary 中移除所有的鍵和值。 

 

ContainsKey 

確定 Dictionary 是否包含指定的鍵。 

 

ContainsValue 

確定 Dictionary 是否包含特定值。 

 

Equals  

已重載。 確定兩個 Object 實例是否相等。 (從 Object 繼承。)

 

GetEnumerator 

返回循環訪問 Dictionary 的枚舉數。 

 

GetHashCode  

用作特定類型的哈希函數。GetHashCode 適合在哈希算法和數據結構(如哈希表)中使用。 (從 Object 繼承。)

 

GetObjectData 

實現 System.Runtime.Serialization.ISerializable 接口,並返回序列化 Dictionary 實例所需的數據。 

 

GetType  

獲取當前實例的 Type。 (從 Object 繼承。)

 

OnDeserialization 

實現 System.Runtime.Serialization.ISerializable 接口,並在完成反序列化之后引發反序列化事件。 

 

ReferenceEquals  

確定指定的 Object 實例是否是相同的實例。 (從 Object 繼承。)

 

Remove 

從 Dictionary 中移除所指定的鍵的值。 

 

ToString  

返回表示當前 Object 的 String。 (從 Object 繼承。)

 

TryGetValue 

獲取與指定的鍵相關聯的值。 

 

6.Hashtable類 

一、哈希表(Hashtable)簡述
     在.NET Framework中,Hashtable是System.Collections命名空間提供的一個容器,用於處理和表現類似key/value的鍵值對,其中key通常可用來快速查找,同時key是區分大小寫;value用於存儲對應於key的值。Hashtable中key/value鍵值對均為object類型,所以Hashtable可以支持任何類型的key/value鍵值對.

二、哈希表的簡單操作
在哈希表中添加一個key/value鍵值對:HashtableObject.Add(key,value);
在哈希表中去除某個key/value鍵值對:HashtableObject.Remove(key);
從哈希表中移除所有元素:                HashtableObject.Clear(); 
判斷哈希表是否包含特定鍵key:         HashtableObject.Contains(key);
下面控制台程序將包含以上所有操作:

using System;
using System.Collections; //使用Hashtable時,必須引入這個命名空間
class hashtable
{
    public static void Main()
   {
   Hashtable ht=new Hashtable(); //創建一個Hashtable實例
    ht.Add("E","e");//添加key/value鍵值對
    ht.Add("A","a");
    ht.Add("C","c");
    ht.Add("B","b");
    string s=(string)ht["A"];
    if(ht.Contains("E")) //判斷哈希表是否包含特定鍵,其返回值為true或false
      Console.WriteLine("the E key:exist");
    ht.Remove("C");//移除一個key/value鍵值對
     Console.WriteLine(ht["A"]);//此處輸出a
     ht.Clear();//移除所有元素
     Console.WriteLine(ht["A"]); //此處將不會有任何輸出
    }
}


三、遍歷哈希表
遍歷哈希表需要用到DictionaryEntry Object,代碼如下:

for(DictionaryEntry de in ht) //ht為一個Hashtable實例
{
    Console.WriteLine(de.Key);//de.Key對應於key/value鍵值對key
    Console.WriteLine(de.Value);//de.Key對應於key/value鍵值對value
}


四、對哈希表進行排序
     對哈希表進行排序在這里的定義是對key/value鍵值對中的key按一定規則重新排列,但是實際上這個定義是不能實現的,因為我們無法直接在Hashtable進行對key進行重新排列,如果需要Hashtable提供某種規則的輸出,可以采用一種變通的做法:

ArrayList akeys=new ArrayList(ht.Keys); //別忘了導入System.Collections
akeys.Sort(); //按字母順序進行排序
foreach(string skey in akeys)
{
    Console.Write(skey + ":");
    Console.WriteLine(ht[skey]);//排序后輸出
}

哈希表,名-值對。類似於字典(比數組更強大)。哈希表是經過優化的,訪問下標的對象先散列過。如果以任意類型鍵值訪問其中元素會快於其他集合。 

GetHashCode()方法返回一個int型數據,使用這個鍵的值生成該int型數據。哈希表獲取這個值最后返回一個索引,表示帶有給定散列的數據項在字典中存儲的位置。 

Hashtable 和 Dictionary <K, V> 類型 
 1:單線程程序中推薦使用 Dictionary, 有泛型優勢, 且讀取速度較快, 容量利用更充分.
 2:多線程程序中推薦使用 Hashtable, 默認的 Hashtable 允許單線程寫入, 多線程讀取, 對 Hashtable 進一步調用 Synchronized() 方法可以獲得完全線程安全的類型. 而 Dictionary 非線程安全, 必須人為使用 lock 語句進行保護, 效率大減.
 3:Dictionary 有按插入順序排列數據的特性 (注: 但當調用 Remove() 刪除過節點后順序被打亂), 因此在需要體現順序的情境中使用 Dictionary 能獲得一定方便.

 

HashTable中的key/value均為object類型,由包含集合元素的存儲桶組成。存儲桶是 HashTable中各元素的虛擬子組,與大多數集合中進行的搜索和檢索相比,存儲桶可令搜索和檢索更為便捷。每一存儲桶都與一個哈希代碼關聯,該哈希代碼是使用哈希函數生成的並基於該元素的鍵。HashTable的優點就在於其索引的方式,速度非常快。如果以任意類型鍵值訪問其中元素會快於其他集合,特別是當數據量特別大的時候,效率差別尤其大。

HashTable的應用場合有:做對象緩存,樹遞歸算法的替代,和各種需提升效率的場合。

    //Hashtable sample
    System.Collections.Hashtable ht = new System.Collections.Hashtable(); 
    //--Be careful: Keys can't be duplicated, and can't be null----
    ht.Add(1, "apple");
    ht.Add(2, "banana");
    ht.Add(3, "orange");     
    //Modify item value:
    if(ht.ContainsKey(1))
        ht[1] = "appleBad"; 
    //The following code will return null oValue, no exception
    object oValue = ht[5];      
    //traversal 1:
    foreach (DictionaryEntry de in ht)
    {
        Console.WriteLine(de.Key);
        Console.WriteLine(de.Value);
    } 
    //traversal 2:
    System.Collections.IDictionaryEnumerator d = ht.GetEnumerator();
    while (d.MoveNext())
    {
        Console.WriteLine("key:{0} value:{1}", d.Entry.Key, d.Entry.Value);
    } 
    //Clear items
    ht.Clear();


Dictionary和HashTable內部實現差不多,但前者無需裝箱拆箱操作,效率略高一點。

    //Dictionary sample
    System.Collections.Generic.Dictionary<int, string> fruits =          new System.Collections.Generic.Dictionary<int, string>(); 
    fruits.Add(1, "apple");
    fruits.Add(2, "banana");
    fruits.Add(3, "orange"); 
    foreach (int i in fruits.Keys)
    {
        Console.WriteLine("key:{0} value:{1}", i, fruits);     }

    if (fruits.ContainsKey(1))
    {
        Console.WriteLine("contain this key.");
    }


HashTable是經過優化的,訪問下標的對象先散列過,所以內部是無序散列的,保證了高效率,也就是說,其輸出不是按照開始加入的順序,而Dictionary遍歷輸出的順序,就是加入的順序,這點與Hashtable不同。如果一定要排序HashTable輸出,只能自己實現:

    //Hashtable sorting
    System.Collections.ArrayList akeys = new System.Collections.ArrayList(ht.Keys); //from Hashtable
    akeys.Sort(); //Sort by leading letter
    foreach (string skey in akeys)
    {
        Console.Write(skey + ":");
        Console.WriteLine(ht[skey]);
    }

 

HashTable與線程安全:

為了保證在多線程的情況下的線程同步訪問安全,微軟提供了自動線程同步的HashTable: 

如果 HashTable要允許並發讀但只能一個線程寫, 要這么創建 HashTable實例:

    //Thread safe HashTable
    System.Collections.Hashtable htSyn = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());

這樣, 如果有多個線程並發的企圖寫HashTable里面的 item, 則同一時刻只能有一個線程寫, 其余阻塞; 對讀的線程則不受影響。

 

另外一種方法就是使用lock語句,但要lock的不是HashTable,而是其SyncRoot;雖然不推薦這種方法,但效果一樣的,因為源代碼就是這樣實現的:

//Thread safe

private static System.Collections.Hashtable htCache = new System.Collections.Hashtable ();

 

public static void AccessCache ()

{

    lock ( htCache.SyncRoot )

    {

        htCache.Add ( "key", "value" );

 

        //Be careful: don't use foreach to operation on the whole collection

        //Otherwise the collection won't be locked correctly even though indicated locked

        //--by MSDN

    }

}

 

 

//Is equivalent to 等同於 (lock is equivalent to Monitor.Enter and Exit()

public static void AccessCache ()

{

    System.Threading.Monitor.Enter ( htCache.SyncRoot );

 

    try

    {

        /* critical section */

        htCache.Add ( "key", "value" );

 

        //Be careful: don't use foreach to operation on the whole collection

        //Otherwise the collection won't be locked correctly even though indicated locked

        //--by MSDN

    }

    finally

    {

        System.Threading.Monitor.Exit ( htCache.SyncRoot );

    }

}

7. Stack類 

Stack:棧,表示對象的簡單的后進先出非泛型集合。Push方法入棧,Pop方法出棧。

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace ConsoleApplication1
{
   class Program
{
       static void Main(string[] args)
       {
           Stack sk = new Stack();
            Stack sk2 = new Stack();
           foreach (int i in new int[4] { 1, 2, 3, 4 })
           {
               sk.Push(i);//入棧
                sk2.Push(i);
            }

            foreach (int i in sk)
           {
               Console.WriteLine(i);//遍歷
            }

           sk.Pop();//出棧
           Console.WriteLine("Pop");
           foreach (int i in sk)
            {
               Console.WriteLine(i);
            }

           sk2.Peek();//彈出最后一項不刪除
            Console.WriteLine("Peek");
           foreach (int i in sk2)
           {
                Console.WriteLine(i);
            }
       }
    }
}


 

8.Queue類 

隊列,先進先出。enqueue方法入隊列,dequeue方法出隊列。 

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace ConsoleApplication1
{
    class Program
    {
       static void Main(string[] args)
       {
           Queue qu = new Queue();
            Queue qu2 = new Queue();
           foreach (int i in new int[4] { 1, 2, 3, 4 })
           {
                qu.Enqueue(i);//入隊
                qu2.Enqueue(i);
            }

           foreach (int i in qu)
           {
               Console.WriteLine(i);//遍歷
            }

            qu.Dequeue();//出隊
            Console.WriteLine("Dequeue");
           foreach (int i in qu)
           {
                Console.WriteLine(i);
           }

           qu2.Peek();//返回位於 Queue 開始處的對象但不將其移除。
           Console.WriteLine("Peek");
           foreach (int i in qu2)
           {
               Console.WriteLine(i);
           }
       }
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM