C#?泛型集合類List<T>使用總結(jié)
C#中List可謂是使用最廣泛的一種數(shù)據(jù)類型了,使用他來規(guī)范數(shù)據(jù)時(shí),往往會涉及到對數(shù)據(jù)的處理操作,相關(guān)處理數(shù)據(jù)方法也非常豐富,本文將簡單介紹為何使用它,以及部分處理方法的靈活使用。
為什么選擇使用List,而不是使用Array,或者ArryList
首先要說下數(shù)組的局限性
(1) 數(shù)組中元素是固定的:類型和數(shù)量都必須確定!一旦定義,無法改變其元素總數(shù)
(2) 如果使用數(shù)組類型存儲數(shù)據(jù),一旦項(xiàng)目需求有變化,那必須修改原數(shù)組相關(guān)代碼,得不償失
(3) 如果數(shù)據(jù)總數(shù)非常大,那數(shù)組在定義時(shí)就要把長度(即元素總數(shù))定義的非常大,造成了存儲空間的巨大浪費(fèi)!
而List跟數(shù)組比較,他可以動(dòng)態(tài)增減元素個(gè)數(shù),無任何限制,直接秒殺數(shù)組
當(dāng)然,實(shí)際項(xiàng)目開發(fā)中,對于一些固定的枚舉值,類型集合等,或相關(guān)數(shù)據(jù)處理中,使用數(shù)組還是相當(dāng)方便的,它并不是沒用的,而是相比較List,使用的空間小一些罷了(存在即有用!)
然后再說下ArryList
這個(gè)直接截圖一下官網(wǎng)的相關(guān)建議
既然官網(wǎng)都不建議使用,那可見它真的不常用,而不是不能用
沒有使用價(jià)值的東西不會被留下來的,對吧!
跟List比較,他還是有一個(gè)優(yōu)點(diǎn)的,就是他可以存儲類型不一樣的對象數(shù)據(jù),而List泛型集合類,其中T必須是對他存儲元素對象的約束,必須一致性!
ArrayList存儲的對象如果是值類型,那就涉及到裝箱操作,這個(gè)對程序性能影響很大,所以不到萬不得已,還是不要用!
而且ArrayList里面存放元素對象類型都不一致,在C#(強(qiáng)類型語言)中處理時(shí),還需要判斷,還要涉及到頻繁裝箱拆箱,性能不說,這不是自討苦吃嘛....
其實(shí)就跟強(qiáng)類型語言和弱類型語言一樣,如果把js比作弱類型,那ts就是強(qiáng)類型,js寫起來很爽(var聲明變量時(shí),變量幾乎可以是任意類型...),但是出現(xiàn)報(bào)錯(cuò)、異常,找起來會相當(dāng)麻煩,因?yàn)閷懙臅r(shí)候,約束的少,那最后運(yùn)行的時(shí)候,都會補(bǔ)回來的!而ts有類型約束以后,寫起來有了一些束手束腳,但是基本不會出錯(cuò),而且寫多了都一樣!這就是大部分后端語言都是強(qiáng)類型的一個(gè)重要原因吧(個(gè)人觀點(diǎn)....)!
List特點(diǎn):只能添加一種數(shù)據(jù)類型,可以是基本的值類型也可以實(shí)引用類型,一旦數(shù)據(jù)類型確定,不可更改!
List做數(shù)據(jù)處理時(shí),完全可以采用強(qiáng)大的Linq,處理起來那是相當(dāng)?shù)姆奖鉢
去重、交集、并集、差集操作
注:這里僅介紹當(dāng)List中T為引用類型(對象)時(shí),基本類型(值類型)就不說了,因?yàn)榭梢灾苯佑茫?...引用類型則不行!
另外還一個(gè)類型比較特殊,也要單獨(dú)拿出來提一嘴,就是string,在C#中它屬于引用類型,但是它類似于值類型,可以直接進(jìn)行比較,在這完全可以歸屬到值類型當(dāng)中了。
當(dāng)然使用Linq中GoupBy + Select等方法還是可以做到去重的,但是這里說的并不是這些東西,而是直接使用
Intersect
、Except
、Distinct
、Union
那么為什么引用類型不能直接比較呢,其實(shí)稍微懂一點(diǎn)底層的都知道,引用類型,引用兩個(gè)字就道出了緣由!其值為一個(gè)引用地址,在棧內(nèi)存中,地址是唯一的,但是也有可能兩個(gè)地址指向同一個(gè)堆中的值呢....
因此要想比較,先把他的值點(diǎn)出來比較,可以只比較某一個(gè)值,也可以是全部
重寫Equals() 和 GetHashCode()
為什么要重新呢,因?yàn)檫@些比較方法的內(nèi)部就是調(diào)用者兩個(gè)方法進(jìn)行比較的,他們僅適用于值類型的比較,對象需要重寫內(nèi)部邏輯了!
要想重寫,需要寫一個(gè)類,繼承IEqualityComparer接口即可
public class MyComparer : IEqualityComparer<Person> { public bool Equals([AllowNull] Person x, [AllowNull] Person y) { return x.name == y.name && x.age == y.age; } public int GetHashCode([DisallowNull] Person obj) { return obj.name.GetHashCode() + obj.age.GetHashCode(); //return obj.name.GetHashCode() ^ obj.age.GetHashCode();// 兩種寫法都可以 } }
其實(shí)上面寫法還是有點(diǎn)不嚴(yán)謹(jǐn)
(1)沒有null判斷,如果某一屬性值為空,那就可能拋異常
(2)并未將對象的所有屬性進(jìn)行比較,如上面,僅僅比較名稱和年齡,那全國20歲叫張三的人肯定不止一個(gè),達(dá)不到目的了(這里僅僅是舉個(gè)例子,具體比較多少屬性,還是根據(jù)項(xiàng)目中實(shí)際情況而定的...如果有Id,那完全可以比較Id不是更快....)
把(1)加進(jìn)去重新寫一遍
public class MyComparer : IEqualityComparer<Person> { public bool Equals([AllowNull] Person x, [AllowNull] Person y) { if(x == null || y == null) return false; if(x.name == y.name && x.age == y.age) return true; return false; } public int GetHashCode([DisallowNull] Person obj) { if(obj == null) return 0; return obj.name.GetHashCode() + obj.age.GetHashCode(); //return obj.name.GetHashCode() ^ obj.age.GetHashCode();// 兩種寫法都可以 } }
簡單使用
- 交集
using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; namespace ConsoleApp1 { class Program { static void Main(string[] args) { //交集:集合A.Intersect(集合B) var _old = new List<Person> { new Person{name="zs",age=21}, new Person{name="ls",age=10}, new Person{name="ww",age=13}, new Person{name="ls",age=10}, new Person{name="ww",age=13} }; var _new = new List<Person> { new Person{name="zs",age=21}, new Person{name="ls",age=31}, new Person{name="ww3",age=13} }; var _obj = _old.Intersect(_new,new MyComparer()).ToList(); for (int i = 0; i < _obj.Count; i++) { var x = _obj[i]; Console.WriteLine("name:{0},age:{1}", x.name, x.age); //結(jié)果: name:zs,age:21 } Console.ReadLine(); } } public class Person { public string name { get; set; } public int age { get; set; } } }
- 差集
var _oj2 = _old.Except(_new, new MyComparer()).ToList(); //結(jié)果: name:ls,age:10 name:ww,age:13
- 并集
var _oj2 = _old.Union(_new, new MyComparer()).ToList(); //結(jié)果: name:zs,age:21 name:ls,age:10 name:ww,age:13 name:ls,age:31 name:ww3,age:13
- 去重
var _oj2 = _old.Distinct(new MyComparer()).ToList(); //結(jié)果: name:zs,age:21 name:ls,age:10 name:ww,age:13
到此這篇關(guān)于C# 泛型集合類List<T>使用總結(jié)的文章就介紹到這了,更多相關(guān)C# 泛型List<T>內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# 對PDF文檔加密、解密(基于Spire.Cloud.SDK for .NET)
這篇文章主要介紹了C# 基于Spire.Cloud.SDK for .NET對PDF文檔進(jìn)行加密解密,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07C#開發(fā)之int與string轉(zhuǎn)化操作
這篇文章主要介紹了C#開發(fā)之int與string轉(zhuǎn)化操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12C#實(shí)現(xiàn)用戶自定義控件中嵌入自己的圖標(biāo)
這篇文章主要介紹了C#實(shí)現(xiàn)用戶自定義控件中嵌入自己的圖標(biāo),較為詳細(xì)的分析了C#實(shí)現(xiàn)自定義控件中嵌入圖標(biāo)的具體步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-03-03C#爬蟲基礎(chǔ)之HttpClient獲取HTTP請求與響應(yīng)
這篇文章介紹了C#使用HttpClient獲取HTTP請求與響應(yīng)的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05C#簡單嵌套flash讀取數(shù)據(jù)的實(shí)現(xiàn)代碼
這篇文章主要介紹了C#簡單嵌套flash讀取數(shù)據(jù)的實(shí)現(xiàn)代碼,有需要的朋友可以參考一下2013-11-11Entity?Framework代碼優(yōu)先(Code?First)模式
這篇文章介紹了Entity?Framework代碼優(yōu)先(Code?First)模式,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06