1. 程式人生 > >C#高級編程四十八天----列表

C#高級編程四十八天----列表

don 合作 racer 變量 去掉 line 實現 abc clas

C#中的List

C#deList怎麽樣?List<T>類是ArrayList類的泛型等效類,該類使用大小可按需動態增長的數組實現List<T>泛型接口.

泛型的優點:它為使用C#語言編寫面向對象程序添加了極大的效力和靈活性,不會強行對值類型進行裝箱和拆箱,或對引用類型進行向下強制類型轉化,所以性能得到提高.

性能註意事項:再決定使用List<T>還是使用ArrayList(兩者具有類似的功能),記住IList<T>類在大多數情況下運行得更好而且是類型安全的.假設對IList<T>類的類型T使用引用類型,則兩個類的行為是全然同樣的

,可是假設對類型T使用值類型,則須要考慮實現和裝箱問題.

C#List的基礎經常用法:

一.聲明:

1. List<T> list=new List<T>():

T為列表中元素類型,如今以string類型作為樣例:

List<string> list=new List<string>():

2.List<T> list = new List<T>(IEnumerable<T> collection);

以一個集合作為參數創建List:

string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };

List<string> testList = new List<string>(temArr);

二.加入元素:

1. List.Add( Titem)加入一個元素

比如:testList.Add(“hahaha”);

2. List.AddRange(IEnumerable <T> collection) 加入一組元素

: string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };

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

testList.AddRange(temArr);

3. Insert(int index ,T item) ; index位置加入一個元素

:testList.Insert(1,”hello”);

三.遍歷List中的元素:

案例:

string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };

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

testList.AddRange(temArr);

foreach (var item in testList)

{

Console.WriteLine(item);

}

四.刪除元素:

1.List.Remove(T item)刪除一個值

:mList.Remove(“hahaha”);

2.List.RemoveAt(int index);刪除下標為index 的元素

:mList.RemoveAt(0);

3.List.RemoveRange(int index , int count);從下標index開始,刪除count個元素

:mList.RemoveRange(3,2);

五.推斷某個元素是否在該List:

List.Contains(T item) 返回truefalse,非常有用

: string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };

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

testList.AddRange(temArr);

if (testList.Contains("Hunter"))

{

Console.WriteLine("There is Hunter in the list");

}

else

{

testList.Add("Hunter");

Console.WriteLine("Add Hunter successfully.");

}

六.給List裏面的元素排序:

List.Sort();

:mList.Sort();

.List裏面元素順序反轉:

  List. Reverse ()能夠不List. Sort ()配合使用,達到想要的效果

  例:

  mList.Sort();

  八、List清空:

  List. Clear ()

  例:

  mList.Clear();

  九、獲得List中元素數目:

  List. Count ()返回int

  例:

  in tcount = mList.Count();

  Console.WriteLine("The num of elements in the list: "+count);

綜合案例:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace 集合

{

class Program

{

static void Main(string[] args)

{

//比較List<T>(泛型的)ArrayList(非泛型的)

People p1 = new People("zhangsan", 21);

People p2 = new People("lisi", 11);

People p3 = new People("wangwu", 41);

//People對象加到集合中

List<People> list = new List<People>(4);

list.Add(p1);

list.Add(p2);

list.Add(p3);

/*假設不指定list容量大小,默認是0,僅僅要有元素增加時,會自己主動擴展到4,假設第五個元素增加時

* 就變成了8,第九個元素增加時,就變成了16

* 能夠看出,容量總是成倍的增長,擴展時要又一次開辟內存,這樣會影響效率,假設事先知道元素個數,

* 或者可能推斷個數,最好給出個大體的容量值

* 我們增加了三個元素,就設容量大小為4.註意:設為4不是說僅僅能存放四個元素

* 而是說,假設超出四個,一樣會成倍擴展,這樣做是為了減小擴展帶來的開銷

*/

/*

* 這種方法作用是清楚多於的沒實用的內存空間.比如:假設開辟大小為100

* 可是我們僅僅用了4,其余的不用,是不是浪費

* 本方法調用時會檢查元素個數是不是占到了容量的90%以上

* 假設是,則不進行回收

*/

list.TrimExcess();

/*ArrayList方法和List<T>使用方法一樣,不同的是,它是對象集合

* 參數是object這樣會有裝箱拆箱的可能

* 所以盡量使用List<>

*/

/*

* 1.初始化集合器

* C#3.0開始,提供了初始化功能,可是並沒有反映到IList代碼中

* IList,一樣也是把它轉化成Add方法調用

*/

List<int> l2 = new List<int>() { 1, 2, 3, 4, 5 };

/*

* 2.加入元素AddRange()方法能夠一次性加入一批對象

*/

List<People> lists = new List<People>(10);

//參數是一個必須可能叠代的對象,也可能是一個數組

list.AddRange(new People[] { new People("aladdin", 20), new People("zhao", 6) });

//構造傳入批量參數,AddRange效果一樣

List<People> myList = new List<People>(new People[] { new People("aladdin", 20), new People("zhao", 6) });

/*

* 3.插入元素

* 使用Insert()方法,能夠在指定位置插入元素

* 例 我們在1的位置插入,則最後變成了aladdin jacky zhao..插入意思就是,這個位我占了,

* 曾經占這位的和他之後的,通通往後移一位

*/

myList.Insert(1, new People("Jacky", 22));

foreach (var p in myList)

{

Console.WriteLine(p.name);

}

/*

*4.訪問元素

*ArrayListList<T>都是提供了索引器來訪問的

*/

Console.WriteLine("*********訪問元素********");

for (int i = 0; i < myList.Count; i++)

{

Console.WriteLine(myList[i].name);

}

//還能夠使用foreach叠代器來實現

/*

* public delegate void Action<T>(T obj);用托付作為參數

*/

Console.WriteLine("********foreach方法輸出********");

myList.ForEach(param => Console.WriteLine(param.name));

/*

* 5.刪除元素

* 刪除元素能夠使用RemoveAt()直接傳入索引器值

* 將第一個元素直接刪除

*/

myList.RemoveAt(0);

List<People> lists2 = new List<People>(10);

People per1 = new People("aladdin", 100);

People per2 = new People("zhao", 100);

People per3 = new People("jacky", 100);

lists2.Add(per1);

lists2.Add(per2);

lists2.Add(per3);

lists2.Remove(per3);

Console.WriteLine("***********刪除後的元素*********");

foreach (var per in lists2)

{

Console.WriteLine(per.name);

}

/*

* 從結果能夠看出,名稱為jacky的元素被刪除了

* 以下說一下Remove方法的刪除過程

* IndexOf方法確定出對象的索引,然後按索引刪除

* IndexOf方法內,首先檢查元素是不是實現了IEquatable接口,假設是,就調用這個

* 這個接口的Equals()方法

* 假設沒有實現,則掉用Object中的Equals方法比較元素(也就是地址比較)

* 以上我們刪除per3,非常明顯是一個地址,所以被刪除了

* 以下我們改裝People,實現了IEquatable<People,

* 比較方法中,始終返回false,per3會比較失敗,不會被刪除

* 結果三個都在

* 假設要刪除對象,最好使用索引直接刪除,由於Remove方法經歷了一系列過程後,最後才按索引刪除!

*

* RemoveRange()方法刪除一個範圍

* 第一個參數:開始位置;第二個參數:個數

* lists2.RemoveRange(1,2);

* 使用foreach查看批量刪除後的結果

* foreach (var per in lists2)

*{

* Console.WriteLine(per.name);

*}

*

*/

/*

* 6.搜索

* 搜索有非常多方式,能夠使用

* IndexOf,LastIndexOf,FindIndex,FindLastIndex,Find,FindLast

* 假設指示查看元素的存在情況,能夠使用Exists()方法

* IndexOf()方法須要將一個對象做參數,假設存在,就返回本元素在集合中的索引,

* 假設找不到就返回-1,IndexOf還能夠使用IEquatable接口來比較元素

*/

List<People> ls3 = new List<People>(10);

People person1 = new People("aladdin",100);

People person2 = new People("zhao",100);

People person3 = new People("jacky",100);

ls3.Add(person1);

ls3.Add(person2);

ls3.Add(person3);

//為了使用默認的地址比較,我們把People的接口臨時去掉

int index = ls3.IndexOf(person3);

Console.WriteLine("per3的索引 : "+index);

//還能夠指定搜索範圍 從第三個開始,範圍長度為1

int index2 = ls3.IndexOf(person3, 2, 1);

Console.WriteLine(index2);

//FindIndex()方法用來搜索帶有一定特性的元素

//用托付做參數 public delegate bool Predicate<T>(T obj);

int index3 = ls3.FindIndex(param => param.name.Equals(""));

Console.WriteLine(index3);//2

//FindLastIndex是從 後面查第一個出現的元素,由於我們這裏沒有反復元素,所以

//體現不出它僅僅能查找一個,就停下來的效果

int index4 = ls3.FindLastIndex(p => p.name.Equals("aladdin"));

Console.WriteLine(index4);

//Find方法與FindIndex方法用於一樣,不同的是,它返回的是元素本身

People ppp = ls3.Find(p => p.name.Equals("jacky"));

Console.WriteLine(ppp);

/*

* 假設要查找全部的匹配元素,而不是找到第一個就停下來,就是用FindAll()方法

* 我們查找全部年紀等於100的對象,3個都符合

*/

List<People> newList = ls3.FindAll(p => p.age == 100);

Console.WriteLine("**********查找全部**********");

foreach (var p in newList)

{

Console.WriteLine(p.name);

}

/*

* 7.排序

* List能夠利用Sort方法排序,實現算符是高速排序

* 本方法有好幾個重載

* public void Sort()僅僅對元素實現了IComparable才幹使用這種方法 ,假設實現了則,能夠直接調用一次sort之後,就排好序了

* public void Sort(Comparison<T> comparison)我們的Person並沒有實現那個接口,所以要用泛型托付當參數的方法

* public void Sort(IComparer<T>(T x , T y))泛型接口當參數 public delegate int Comparison<T>(T x, T y);

*

* public void Sort(int index ,int count ,IComparer<T> comparer) 能夠指定範圍

*/

List<People> ls4 = new List<People>(10);

People person4 = new People("aladdin",100);

People person5 = new People("zhao", 33);

People person6 = new People("jacky", 44);

ls4.Add(person4);

ls4.Add(person5);

ls4.Add(person6);

ls4.Sort(MyComparFunc);

Console.WriteLine("***********排序後的************");

foreach (var p in ls4)

{

Console.WriteLine(p.name+p.age);

}

Console.WriteLine("***********顛倒順序***********");

ls4.Reverse();

foreach (var p in ls4)

{

Console.WriteLine(p.name+p.age);

}

/*

* 8.類型轉換 能夠將集合中的元素轉換成隨意類型的元素,比方,

* 我們要將集合中的People轉換成為Racer對象Racer僅僅包括名字,沒有年紀

* public List<T Output>ConvertAll<TOutput>(Converter<T, TOutput> converter);

* public delegate T Output Converter<T Input, T Output>(T Input input); 托付參數

*/

List<Racer> ls5 = ls4.ConvertAll<Racer>((input) => new Racer(input.name));

Console.WriteLine("***********轉換後的玩意***********");

foreach (var r in ls5)

{

Console.WriteLine(r.name);

}

/*9.僅僅讀集合

* 在創建完集合以後,肯定是可讀的,假設不是,他就不能再加入新元素了

* 可是,假設是覺得填充完成,不要再做改動

* 能夠使用僅僅讀集合,使用AsReadOnly方法返回ReadOnlyCollection<T>

* 類型,它與List<>操作是一樣的,可是一但有改動集合的操作,就會拋出異常

* 它屏蔽了通常的Add方法

*/

IReadOnlyCollection<Racer> persss = ls5.AsReadOnly();

Console.WriteLine("輸出僅僅讀集合");

foreach (var r in persss)

{

Console.WriteLine(r.name);

}

Console.ReadKey();

}

public static int MyComparFunc(People p1, People p2)

{

if (p1.age==p2.age)

{

return 0;

}

else if (p1.age > p2.age)

{

return 1;

}

else

{

return -1;

}

}

}

public class People

{

public string name;

public int age;

public People(string name, int age)

{

this.name = name;

this.age = age;

}

}

public class Racer

{

public string name;

public Racer(string name)

{

this.name = name;

}

}

}

C#中數組,ArrayListList三者的差別

C#中數組,ArrayList,List都可以存儲一組對象,那麽三者究竟有何差別呢?

數組

數組在C#中最早出現的.在內存中是連續存儲的,所以他的索引速度非常快,並且賦值與改動元素也非常easy.

案例:

string [] s=new string [2];

//賦值

s[0]=”a”;

s[1]=”b”;

//改動

s[1]=”aa”;

可是數組存在一些不足的地方.在數組的兩個數據間插入數據是非常麻煩的,並且在聲明數組的時候必須制定數組的長度,數組的長度過長,會造成內存浪費,過界會造成數據溢出的錯誤.假設在聲明數組的時候我們不清楚數組的長度,就會變得非常麻煩.

針對數組的這些缺點,C#中最先提供了ArrayList對象來克服這些缺點.

ArrayList

ArrayList是命名空間System.Collections下的一部分,在使用該類時必須進行引用,同一時候繼承了IList接口,提供了數據存儲和檢索.ArrayList對象的大小是依照當中存儲的數據來動態擴充與收縮的.所以,在聲明ArrayList對象時並不須要指定它的長度.

案例:

ArrayList list1=new ArrayList();

//新增數據

list1.Add(“cde”);

list1.Add(5678);

//改動數據

list1[2]=34;

//移除數據

list1.Remove(0);

//插入數據

list1.Insert(0,”qwe”);

從上面樣例看,ArrayList好像是攻克了數組中的全部的缺點,為什麽又會有List?

我們從上面的樣例看,List,我們不僅插入了字符串cde,並且插入了數字5678.這樣在ArrayList中插入不同類型的數據是同意的.由於ArrayList會把全部插入當中的數據當做為object類型來處理,在我們使用ArrayList處理數據時,非常可能會報類型不匹配的錯誤,也就是ArrayList不是類型安全的.在存儲或檢索值類型時通常發生裝箱和拆箱操作,帶來非常呆的性能損耗.

裝箱與拆箱的概念:

簡單的說:

裝箱:就是將值類型的數據打包到引用類型的實例中

比方將string類型的值abc賦給object對象obj

案例:

string i=”abc”;

object obj=(object)i;

拆箱:就是從引用數據中提取值類型

比方將object對象obj的值賦給string類型的變量i :

object obj=”abc”;

string i=(string)obj;

裝箱與拆箱的過程是非常損耗性能的.

泛型List

由於ArrayList存在不安全類型與裝箱拆箱的缺點,所以出現了泛型的概念.List類是ArrayList類的泛型等效類,他的大部分使用方法都與ArrayList相似,由於List類也繼承IList接口.最關鍵的卻別在於,在聲明List集合時,我們同事須要為其聲明List集合內數據的對象類型.

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

//新增數據

list.Add(“abc”);

//改動數據

list[0]=”def”;

//移除數據

list.Remove(0);

上例中,假設我們往List集合中插入int數組123,IDE就會報錯,且不能通過編譯.這樣就避免了前面講的類型安全問題與拆箱的性能問題了.

總結:數組的容量是固定的,您僅僅能一次獲取或設置一個元素的值,ArrayListList<T>的容量可依據須要自己主動擴充,改動,刪除或插入數據.

數組能夠具有多個維度,ArrayListList<T>時鐘僅僅具有一個維度.可是您能夠輕松創建數組列表或列表的列表.特定類型(object除外)的數組的性能優於ArrayList的性能.這是由於ArrayList的元素屬於object類型;所以在存儲或檢索值類型時通常發生裝箱和拆箱操作.只是,在不須要又一次分配時(即最初的容量十分接近列表的最大容量),List<T>的性能與同類型的數組十分相近.

在決定使用List<T>還是使用ArrayList(兩者具有類似的功能),記住List<T>類在大多數情況下運行的更好而且是類型安全的.假設對List<T>類的類型T使用引用類型,則兩個類的行為是全然同樣的.可是,假設對類型T使用值類型,則須要考慮實現和裝箱操作.

C#高級編程四十八天----列表