很多非泛型集合類都有對應的泛型集合類,下面是常用的非泛型集合類以及對應的泛型集合類:
非泛型集合類 | 泛型集合類 |
ArrayList | List<T> |
HashTable | DIctionary<T> |
Queue | Queue<T> |
Stack | Stack<T> |
SortedList | SortedList<T> |
我們用的比較多的非泛型集合類主要有 ArrayList類 和 HashTable類。我們經常用HashTable 來存儲將要寫入到數據庫或者返回的信息,在這之間要不斷的進行類型的轉化,增加了系統裝箱和拆箱的負擔,如果我們操縱的數據類型相對確定的化 用 Dictionary<TKey,TValue> 集合類來存儲數據就方便多了,例如我們需要在電子商務網站中存儲用戶的購物車信息( 商品名,對應的商品個數)時,完全可以用 Dictionary<string, int> 來存儲購物車信息,而不需要任何的類型轉化。
List類
注意:此類在 .NET Framework 2.0 版中是新增的。表示可通過索引訪問的對象的強類型列表。提供用於對列表進行搜索、排序和操作的方法。命名空間: System.Collections.Generic,程序集:mscorlib(在 mscorlib.dll 中),List 類是 ArrayList 類的泛型等效類。
//聲明一個泛型類
class TestGenericList
...{
static void Main()
...{
//聲明一個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("馬蜂");
}
}
在決定使用 List 還是使用 ArrayList 類(兩者具有類似的功能)時,記住 List 類在大多數情況下執行得更好並且是類型安全的。如果對 List 類的類型 T 使用引用類型,則兩個類的行爲是完全相同的。但是,如果對類型 T 使用值類型,則需要考慮實現和裝箱問題。
如果對類型 T 使用值類型,則編譯器將特別針對該值類型生成 List 類的實現。這意味着不必對 List 對象的列表元素進行裝箱就可以使用該元素,並且在創建大約 500 個列表元素之後,不對列表元素裝箱所節省的內存將大於生成該類實現所使用的內存。
其實我們也可以自己定義一個泛型類,如下所示:
//聲明一個泛型類
public class ItemList<T>
...{
void Add(T item) ...{ }
}
class TestGenericList
...{
private class ExampleClass ...{ }
static void Main()
...{
// 聲明一個對象,只能加入int型
ItemList<int> list1 = new ItemList<int>();
//聲明一個對象,只能加入Student類型,Student類爲自定義類
ItemList<Student> list2 = new ItemList<Student>();
}
}
泛型的用法還有很多種,如泛型方法,泛型委託,泛型接口等。
List 和 IList的區別 IList <Class1> IList11 =new List <Class1>();
List <Class1> List11 =new List <Class1>();
這兩行代碼,從操作上來看,實際上都是創建了一個List<Class1>對象的實例,也就是說,他們的操作沒有區別。
只是用於保存這個操作的返回值變量類型不一樣而已。
那麼,我們可以這麼理解,這兩行代碼的目的不一樣。
List <Class1> List11 =new List <Class1>();
是想創建一個List<Class1>,而且需要使用到List<T>的功能,進行相關操作。
而
IList <Class1> IList11 =new List <Class1>();
只是想創建一個基於接口IList<Class1>的對象的實例,只是這個接口是由List<T>實現的。
所以它只是希望使用到IList<T>接口規定的功能而已。
C#裏List的用法
主程序代碼:
static void Main(string[] args)
{
ClassList listClass = new ClassList();
Console.WriteLine("請輸入第個字符串");
string a = Console.ReadLine();
Console.WriteLine("請輸入第二個字符串");
string b = Console.ReadLine();
foreach (string n in listClass.strList(a, b))
{
Console.WriteLine(n);
}
類:
class ClassList
{
public List<string> strList(string str1,string str2)
{
string stra = str1 + str2;
string strb = str2 + str1;
string strc = str1 + str1;
List<string> listStr = new List<string>();
listStr.Add(stra);
listStr.Add(strb);
listStr.Add(strc);
return listStr;
}
}
public class Person
{
private string _name;
private string _like;
public string Name
{
get
{
return this._name;
}
set
{
this._name = value;
}
}
public string Like
{
get
{
return this._like;
}
set
{
this._like = value;
}
}
}
IList<Person> myPerson = new List<Person>();
Person person = new Person();
person.Like = "pingpong";
person.Name = "panjun";
myPerson.Add(person);
foreach (Person person1 in myPerson)
{
this.label1.Text += person1.Name + person1.Like;
}
Dictionary
此類在 .NET Framework 2.0 版中是新增的。表示鍵和值的集合。命名空間:System.Collections.Generic,程序集:mscorlib(在 mscorlib.dll 中)
class TestGenericList
...{
static void Main()
...{
//聲明對象,參數表示,鍵是int類型,值是string類型
Dictionary<int, string> fruit = new Dictionary<int, string>();
try...{
//加入重複鍵會引發異常
fruit.Add(1, "蘋果");
fruit.Add(2, "桔子");
fruit.Add(3, "香蕉");
fruit.Add(4, "菠蘿");
//參數錯誤將引發異常,如下所示
//fruit.Add("5", "aa");
}
catch (ArgumentException)
...{
Console.WriteLine("添加錯誤!!!");
}
//因爲引入了泛型,所以鍵取出後不需要進行Object到int的轉換,值的集合也一樣
foreach (int i in fruit.Keys)
...{
Console.WriteLine("鍵是:{0} 值是:{1}",i,fruit[i]);
}
//刪除指定鍵,值
fruit.Remove(1);
//判斷是否包含指定鍵
if (fruit.ContainsKey(1))
...{
Console.WriteLine("包含此鍵");
}
//清除集合中所有對象
fruit.Clear();
}
}
Dictionary遍歷輸出的順序,就是加入的順序,這點與Hashtable不同,其它方法如:ContainsKey ,ContainsValue ,Remove 等,使用方法基本一致。
======================================================================================
.NET(C#) Hashtable Dictionary 探索
先看下面的代碼
using System;
using System.Collections;
namespace NoSortHashtable
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Hashtable hashTable = new Hashtable();
hashTable.Add("hunan","changsha");
hashTable.Add("beijing","beijing");
hashTable.Add("anhui","hefei");
hashTable.Add("sichuan","chengdu");
foreach(string str in hashTable.Keys)
{
Console.WriteLine(str + " : " + hashTable[str]);
}
}
}
}
打印的結果是:
anhui : hefei
hunan : changsha
sichuan : chengdu
beijing : beijing
爲何產生這樣的結果? 我查了MSDN後發現----------------------------------------------------------------------------------------------------Hashtable 對象由包含集合元素的存儲桶組成。存儲桶是 Hashtable 中各元素的虛擬子組,與大多數集合中進行的搜索和檢索相比,存儲桶可令搜索和檢索更爲便捷。每一存儲桶都與一個哈希代碼關聯,該哈希代碼是使用哈希函數生成的並基於該元素的鍵。
哈希函數是基於鍵返回數值哈希代碼的算法。鍵是正被存儲的對象的某一屬性的值。哈希函數必須始終爲相同的鍵返回相同的哈希代碼。一個哈希函數能夠爲兩個不同的鍵生成相同的哈希代碼,但從哈希表檢索元素時,爲每一唯一鍵生成唯一哈希代碼的哈希函數將令性能更佳。
在 Hashtable 中用作元素的每一對象必須能夠使用 GetHashCode 方法的實現爲其自身生成哈希代碼。但是,還可以通過使用接受 IHashCodeProvider 實現作爲參數之一的 Hashtable 構造函數,爲 Hashtable 中的所有元素指定一個哈希函數。
在將一個對象添加到 Hashtable 時,它被存儲在存儲桶中,該存儲桶與匹配該對象的哈希代碼的哈希代碼關聯。在 Hashtable 內搜索一個值時,將爲該值生成哈希代碼,並且搜索與該哈希代碼關聯的存儲桶。
例如,一個字符串的哈希函數可以採用該字符串中每一字符的 ASCII 代碼並它們添加到一起來生成一個哈希代碼。字符串“picnic”將具有與字符串“basket”的哈希代碼不同的哈希代碼;因此,字符串“picnic”和“basket”將處於不同的存儲桶中。與之相比,“stressed”和“desserts”將具有相同的哈希代碼並將處於相同的存儲桶中。
Dictionary 類與 Hashtable 類的功能相同。對於值類型,特定類型(不包括 Object)的 Dictionary 的性能優於 Hashtable,這是因爲 Hashtable 的元素屬於 Object 類型,所以在存儲或檢索值類型時通常發生裝箱和取消裝箱操作。
----------------------------------------------------------------------------------------------------
產生這個結果的原因就是Hashtable內部的排序機制使然,但我現在就是不想排序,我按什麼順序輸入的,就想它再怎麼給我輸出,怎麼辦?google後發現幾個可以解決的辦法,不過都需要自己寫代碼實現比如,繼承hashtable,使用不自動排序的arraylist做中間橋
using System;
using System.Collections;
namespace NoSortHashtable
{
public class NoSortHashtable : Hashtable
{
private ArrayList keys = new ArrayList();
public NoSortHashtable()
{
}
public override void Add(object key, object value)
{
base.Add (key, value);
keys.Add (key);
}
public override ICollection Keys
{
get
{
return keys;
}
}
public override void Clear()
{
base.Clear ();
keys.Clear ();
}
public override void Remove(object key)
{
base.Remove (key);
keys.Remove (key);
}
public override IDictionaryEnumerator GetEnumerator()
{
return base.GetEnumerator ();
}
}
}
或者只要Compare函數的返回結果不等於0就可以添加相同的Key,這樣可以實現既可以排序,又可以有相同的Key值,可能在某些情況下會用得到。 using System;
using System.Collections;
namespace testSortedList
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
SortedList sl = new SortedList(new MySort()); //不排序
sl.Add(333,333);
sl.Add(111,111);
sl.Add(222,222);
sl.Add(111,112);
PrintList(sl);
Console.ReadLine();
}
private static void PrintList(SortedList sl)
{
for(int i=0;i<sl.Count ;i++)
{
Console.WriteLine("{0}\t{1}",sl.GetKey(i),sl.GetByIndex(i));
}//end for
}//end fn()
}
public class MySort:IComparer
{
#region IComparer 成員
public int Compare(object x, object y)
{
return -1;
//排序
// int iResult = (int)x - (int)y;
// if(iResult == 0) iResult = -1;
// return iResult;
}
#endregion
}
}
使用單鏈接列表實現 IDictionary。建議用於通常包含 10 個或 10 個以下項的集合。
最後我測試了使用泛類型的Dictionary<T,T>, 儘管msdn上說hashtable和Dictionary的實現是一樣的,不過同樣的數據,返回的結果卻是不同的,我沒有找到更多的解釋,測試代碼如下
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
namespace NoSortHashtable
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add("hunan","changsha");
ht.Add("beijing","beijing");
ht.Add("anhui","hefei");
ht.Add("sichuan","chengdu");
foreach(string str in ht.Keys)
{
Console.WriteLine(str + " : " + ht[str]);
}
Console.WriteLine("------------------------------------");
Dictionary<String,String> dic = new Dictionary<String,String>();
dic.Add("hunan","changsha");
dic.Add("beijing","beijing");
dic.Add("anhui","hefei");
dic.Add("sichuan","chengdu");
foreach(string str in dic.Keys)
{
Console.WriteLine(str + " : " + dic[str]);
}
Console.WriteLine("------------------------------------");
ListDictionary lsdic = new ListDictionary();
lsdic.Add("hunan","changsha");
lsdic.Add("beijing","beijing");
lsdic.Add("anhui","hefei");
lsdic.Add("sichuan","chengdu");
foreach(string str in lsdic.Keys)
{
Console.WriteLine(str + " : " + lsdic[str]);
}
}
}
}
另外,System.Collections.Specialized.ListDictionary也是可以完成該要求的,不過。。。
========================================================================================
3個對泛型 List 排序的方法
方式1:
List<SoftDrink> list = manager.SoftDrink.ListSoftDrink();
list.Sort(new MyComp().Compare);
list.Sort(new MyCompDesc().Compare);
public class MyComp : IComparer<SoftDrink> {
public int Compare(SoftDrink x, SoftDrink y) {
return String.Compare(x.SerialId, y.SerialId);
}
}
public class MyCompDesc : IComparer<SoftDrink> {
public int Compare(SoftDrink x, SoftDrink y) {
return String.Compare(y.SerialId, x.SerialId);
}
}
方式2:
list.Sort(
new Comparison<SoftDrink>(
delegate(SoftDrink x, SoftDrink y) {
return String.Compare(x.SerialId, y.SerialId);
}));
list.Sort(
new Comparison<SoftDrink>(
delegate(SoftDrink x, SoftDrink y) {
return String.Compare(y.SerialId, x.SerialId);
}));
方式3: 使用 Dynamic Reflection Library
DynamicComparer<SoftDrink> comparer = new DynamicComparer<SoftDrink>("SerialId");
DynamicComparer<SoftDrink> comparerDesc = new DynamicComparer<SoftDrink>("SerialId DESC");
list.Sort(comparer);
list.Sort(comparerDesc);
在List有90筆 SoftDrink的情況下,對List正排倒排連續做1000次
方法1: 0.424 秒
方法2: 0.393 秒
方法3: 1.859 秒
方法3: 0.527 秒 (如果new Comparer()放在迴圈外)
不要覺得 Dynamic Reflection Library 慢就沒用呀,他能容易的對多屬性做排序,而速度差異也不大
比較糟的是,如果我的物件裏有子物件,我要對依子物件的屬性做排序,他就辦不到了。