• 當前位置:首頁 > IT技術 > Windows編程 > 正文

    C#高級編程四十八天----列表
    2021-08-06 16:21:56

    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)?返回true或false,非常有用

    例:????????????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.訪問元素

    ?????????????*ArrayList和List<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#中數組,ArrayList和List三者的差別

    在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處理數據時,非??赡軙箢愋筒黄ヅ涞腻e誤,也就是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就會報錯,且不能通過編譯.這樣就避免了前面講的類型安全問題與拆箱的性能問題了.

    ?

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

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

    ?

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

    ?

    ?

    ?

    ?
    ?
    ?
    ?

    本文摘自 :https://blog.51cto.com/u

    開通會員,享受整站包年服務
    国产呦精品一区二区三区网站|久久www免费人咸|精品无码人妻一区二区|久99久热只有精品国产15|中文字幕亚洲无线码