的使用與性能優(yōu)化指南)
1. VB.NET中的List(Of T)基礎(chǔ)概念在VB.NET中List(Of T)是System.Collections.Generic命名空間中最常用的集合類型之一。它本質(zhì)上是一個(gè)動(dòng)態(tài)數(shù)組提供了比傳統(tǒng)數(shù)組更強(qiáng)大的功能。我第一次接觸List(Of T)是在處理一個(gè)需要?jiǎng)討B(tài)增刪數(shù)據(jù)的項(xiàng)目時(shí)傳統(tǒng)數(shù)組的固定長(zhǎng)度限制讓我頭疼不已而List(Of T)完美解決了這個(gè)問(wèn)題。List(Of T)中的T代表泛型類型參數(shù)這意味著我們可以創(chuàng)建任何類型的安全集合。比如List(Of String)存儲(chǔ)字符串集合List(Of Integer)存儲(chǔ)整數(shù)集合。這種強(qiáng)類型特性避免了類型轉(zhuǎn)換錯(cuò)誤是VB.NET類型安全的重要體現(xiàn)。與ArrayList相比List(Of T)最大的優(yōu)勢(shì)在于編譯時(shí)類型檢查不需要頻繁裝箱拆箱對(duì)值類型特別重要更好的性能表現(xiàn)2. List(Of T)的初始化與基本操作2.1 創(chuàng)建和初始化List創(chuàng)建List(Of T)有多種方式每種方式都有其適用場(chǎng)景 方式1創(chuàng)建空列表 Dim names As New List(Of String) 方式2創(chuàng)建并初始化VB 2010及以上版本支持集合初始化器 Dim primes As New List(Of Integer) From {2, 3, 5, 7, 11} 方式3從數(shù)組創(chuàng)建 Dim colorsArray() As String {Red, Green, Blue} Dim colors As New List(Of String)(colorsArray) 方式4指定初始容量當(dāng)你知道大概元素?cái)?shù)量時(shí) Dim bigList As New List(Of Double)(1000)在實(shí)際項(xiàng)目中我通常會(huì)根據(jù)數(shù)據(jù)來(lái)源選擇初始化方式。如果數(shù)據(jù)來(lái)自數(shù)據(jù)庫(kù)查詢方式1配合AddRange最常用如果是硬編碼的配置數(shù)據(jù)方式2更簡(jiǎn)潔。2.2 添加和訪問(wèn)元素Dim fruits As New List(Of String) 添加單個(gè)元素 fruits.Add(Apple) fruits.Add(Banana) 添加多個(gè)元素 fruits.AddRange({Orange, Mango, Grape}) 插入元素 fruits.Insert(1, Peach) 在索引1處插入 訪問(wèn)元素 Dim firstFruit As String fruits(0) Apple Dim lastFruit As String fruits(fruits.Count - 1) Grape一個(gè)常見錯(cuò)誤是直接訪問(wèn)不存在的索引。比如當(dāng)列表為空時(shí)訪問(wèn)fruits(0)會(huì)拋出ArgumentOutOfRangeException。安全的做法是先檢查Count屬性If fruits.Count 0 Then Console.WriteLine(fruits(0)) End If2.3 刪除元素 按值刪除刪除第一個(gè)匹配項(xiàng) fruits.Remove(Banana) 按索引刪除 fruits.RemoveAt(0) 刪除第一個(gè)元素 刪除所有匹配項(xiàng) fruits.RemoveAll(Function(f) f.StartsWith(A)) 刪除所有以A開頭的水果 清空列表 fruits.Clear()在刪除操作中Remove和RemoveAll使用的是相等性比較。對(duì)于自定義類型需要確保正確實(shí)現(xiàn)了Equals方法否則可能會(huì)出現(xiàn)無(wú)法刪除的情況。3. List(Of T)的高級(jí)用法3.1 容量(Capacity)與計(jì)數(shù)(Count)List(Of T)內(nèi)部使用數(shù)組存儲(chǔ)元素Capacity表示內(nèi)部數(shù)組的長(zhǎng)度Count表示實(shí)際元素?cái)?shù)量。當(dāng)添加元素導(dǎo)致Count超過(guò)Capacity時(shí)List會(huì)自動(dòng)擴(kuò)容通常是當(dāng)前容量的2倍。Dim numbers As New List(Of Integer)(4) 初始容量4 Console.WriteLine($初始容量: {numbers.Capacity}) 4 For i As Integer 1 To 5 numbers.Add(i) Console.WriteLine($Count: {numbers.Count}, Capacity: {numbers.Capacity}) Next 輸出 Count: 1, Capacity: 4 ... Count: 5, Capacity: 8 (自動(dòng)擴(kuò)容)在性能敏感的場(chǎng)景合理設(shè)置初始容量可以減少擴(kuò)容帶來(lái)的性能損耗。我曾在處理10萬(wàn)條數(shù)據(jù)時(shí)預(yù)先設(shè)置容量使性能提升了約15%。3.2 查找和判斷Dim numbers As New List(Of Integer) From {1, 3, 5, 7, 9} 判斷是否存在 Dim hasFive As Boolean numbers.Contains(5) True 查找索引 Dim indexOfSeven As Integer numbers.IndexOf(7) 3 Dim lastIndexOf As Integer numbers.LastIndexOf(3) 1 使用謂詞查找 Dim firstEven As Integer numbers.Find(Function(n) n Mod 2 0) 0沒(méi)找到 Dim allEvens As List(Of Integer) numbers.FindAll(Function(n) n Mod 2 0) 空列表對(duì)于復(fù)雜查找Find方法比Where(LINQ)更高效因?yàn)樗业降谝粋€(gè)匹配項(xiàng)就返回而不是遍歷整個(gè)集合。3.3 排序和反轉(zhuǎn)Dim unsorted As New List(Of Integer) From {3, 1, 4, 2} 默認(rèn)排序升序 unsorted.Sort() 1, 2, 3, 4 自定義排序 unsorted.Sort(Function(x, y) y.CompareTo(x)) 降序4, 3, 2, 1 反轉(zhuǎn)順序 unsorted.Reverse() 1, 2, 3, 4對(duì)于自定義類型可以實(shí)現(xiàn)IComparable接口或提供Comparison委托Class Person Public Property Name As String Public Property Age As Integer Public Shared Function CompareByAge(p1 As Person, p2 As Person) As Integer Return p1.Age.CompareTo(p2.Age) End Function End Class Dim people As New List(Of Person) From { New Person With {.Name Alice, .Age 30}, New Person With {.Name Bob, .Age 25} } people.Sort(AddressOf Person.CompareByAge)4. List(Of T)的實(shí)際應(yīng)用示例4.1 數(shù)據(jù)分組處理假設(shè)我們需要處理一批訂單數(shù)據(jù)按客戶分組計(jì)算總金額Class Order Public Property CustomerId As Integer Public Property Amount As Decimal End Class Dim orders As New List(Of Order) From { New Order With {.CustomerId 1, .Amount 100}, New Order With {.CustomerId 2, .Amount 200}, New Order With {.CustomerId 1, .Amount 150} } 按客戶ID分組 Dim grouped orders.GroupBy(Function(o) o.CustomerId) For Each group In grouped Console.WriteLine($客戶 {group.Key} 的總金額: {group.Sum(Function(o) o.Amount)}) Next4.2 批量數(shù)據(jù)操作處理大型數(shù)據(jù)集時(shí)合理使用List的方法可以顯著提高性能 批量添加 Dim largeList As New List(Of Integer) Dim dataToAdd() As Integer GetHugeArrayFromSomewhere() 假設(shè)返回大量數(shù)據(jù) largeList.AddRange(dataToAdd) 比循環(huán)Add高效得多 批量刪除 largeList.RemoveAll(Function(x) x 0) 刪除所有負(fù)數(shù)4.3 與數(shù)組的轉(zhuǎn)換List和數(shù)組經(jīng)常需要互相轉(zhuǎn)換 List轉(zhuǎn)數(shù)組 Dim fruitArray() As String fruits.ToArray() 數(shù)組轉(zhuǎn)List Dim newList As New List(Of String)(fruitArray) 更簡(jiǎn)潔的方式VB 2019 Dim quickList As List(Of String) fruitArray.ToList()在處理文件I/O或與舊代碼交互時(shí)這種轉(zhuǎn)換非常常見。需要注意的是ToList()和ToArray()都會(huì)創(chuàng)建新的集合修改這些新集合不會(huì)影響原List。5. 性能優(yōu)化與最佳實(shí)踐5.1 容量預(yù)分配當(dāng)你知道大概的元素?cái)?shù)量時(shí)預(yù)先設(shè)置容量可以避免多次擴(kuò)容 不好可能多次擴(kuò)容 Dim list1 As New List(Of Integer) For i As Integer 1 To 10000 list1.Add(i) Next 更好預(yù)先分配足夠容量 Dim list2 As New List(Of Integer)(10000) For i As Integer 1 To 10000 list2.Add(i) Next在我的性能測(cè)試中處理10萬(wàn)個(gè)元素時(shí)預(yù)分配容量比不預(yù)分配快約30%。5.2 避免頻繁的Add操作對(duì)于大量數(shù)據(jù)使用AddRange比循環(huán)Add更高效 低效 For Each item In hugeCollection myList.Add(item) Next 高效 myList.AddRange(hugeCollection)5.3 使用正確的查找方法根據(jù)需求選擇最合適的查找方法 只需要知道是否存在Contains最快 If myList.Contains(target) Then ... 需要位置信息IndexOf Dim pos myList.IndexOf(target) 復(fù)雜條件查找Find/FindAll Dim match myList.Find(Function(x) x.Property value)5.4 考慮使用For循環(huán)代替For Each在極高性能要求的場(chǎng)景For循環(huán)比For Each略快 通常這樣寫可讀性好 For Each item In myList 處理item Next 性能更高差異通常很小 For i As Integer 0 To myList.Count - 1 Dim item myList(i) 處理item Next不過(guò)在實(shí)際項(xiàng)目中除非確實(shí)遇到性能瓶頸否則建議優(yōu)先考慮代碼可讀性。5.5 線程安全考慮List(Of T)不是線程安全的。在多線程環(huán)境下應(yīng)該使用鎖或其他同步機(jī)制Private Shared myList As New List(Of String) Private Shared listLock As New Object() 線程安全的添加操作 SyncLock listLock myList.Add(new item) End SyncLock或者考慮使用System.Collections.Concurrent命名空間中的線程安全集合如ConcurrentBag(Of T)。