的使用與性能優(yōu)化指南)
1. VB.NET中的List(Of T)基礎(chǔ)概念在VB.NET中List(Of T)是System.Collections.Generic命名空間中最常用的集合類型之一。它本質(zhì)上是一個動態(tài)數(shù)組提供了比傳統(tǒng)數(shù)組更強(qiáng)大的功能。我第一次接觸List(Of T)是在處理一個需要動態(tài)增刪數(shù)據(jù)的項目時傳統(tǒng)數(shù)組的固定長度限制讓我頭疼不已而List(Of T)完美解決了這個問題。List(Of T)中的T代表泛型類型參數(shù)這意味著我們可以創(chuàng)建任何類型的安全集合。比如List(Of String)存儲字符串集合List(Of Integer)存儲整數(shù)集合。這種強(qiáng)類型特性避免了類型轉(zhuǎn)換錯誤是VB.NET類型安全的重要體現(xiàn)。與ArrayList相比List(Of T)最大的優(yōu)勢在于編譯時類型檢查不需要頻繁裝箱拆箱對值類型特別重要更好的性能表現(xiàn)2. List(Of T)的初始化與基本操作2.1 創(chuàng)建和初始化List創(chuàng)建List(Of T)有多種方式每種方式都有其適用場景 方式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)你知道大概元素數(shù)量時 Dim bigList As New List(Of Double)(1000)在實際項目中我通常會根據(jù)數(shù)據(jù)來源選擇初始化方式。如果數(shù)據(jù)來自數(shù)據(jù)庫查詢方式1配合AddRange最常用如果是硬編碼的配置數(shù)據(jù)方式2更簡潔。2.2 添加和訪問元素Dim fruits As New List(Of String) 添加單個元素 fruits.Add(Apple) fruits.Add(Banana) 添加多個元素 fruits.AddRange({Orange, Mango, Grape}) 插入元素 fruits.Insert(1, Peach) 在索引1處插入 訪問元素 Dim firstFruit As String fruits(0) Apple Dim lastFruit As String fruits(fruits.Count - 1) Grape一個常見錯誤是直接訪問不存在的索引。比如當(dāng)列表為空時訪問fruits(0)會拋出ArgumentOutOfRangeException。安全的做法是先檢查Count屬性If fruits.Count 0 Then Console.WriteLine(fruits(0)) End If2.3 刪除元素 按值刪除刪除第一個匹配項 fruits.Remove(Banana) 按索引刪除 fruits.RemoveAt(0) 刪除第一個元素 刪除所有匹配項 fruits.RemoveAll(Function(f) f.StartsWith(A)) 刪除所有以A開頭的水果 清空列表 fruits.Clear()在刪除操作中Remove和RemoveAll使用的是相等性比較。對于自定義類型需要確保正確實現(xiàn)了Equals方法否則可能會出現(xiàn)無法刪除的情況。3. List(Of T)的高級用法3.1 容量(Capacity)與計數(shù)(Count)List(Of T)內(nèi)部使用數(shù)組存儲元素Capacity表示內(nèi)部數(shù)組的長度Count表示實際元素數(shù)量。當(dāng)添加元素導(dǎo)致Count超過Capacity時List會自動擴(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 (自動擴(kuò)容)在性能敏感的場景合理設(shè)置初始容量可以減少擴(kuò)容帶來的性能損耗。我曾在處理10萬條數(shù)據(jù)時預(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沒找到 Dim allEvens As List(Of Integer) numbers.FindAll(Function(n) n Mod 2 0) 空列表對于復(fù)雜查找Find方法比Where(LINQ)更高效因為它找到第一個匹配項就返回而不是遍歷整個集合。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對于自定義類型可以實現(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)的實際應(yīng)用示例4.1 數(shù)據(jù)分組處理假設(shè)我們需要處理一批訂單數(shù)據(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ù)集時合理使用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) 更簡潔的方式VB 2019 Dim quickList As List(Of String) fruitArray.ToList()在處理文件I/O或與舊代碼交互時這種轉(zhuǎn)換非常常見。需要注意的是ToList()和ToArray()都會創(chuàng)建新的集合修改這些新集合不會影響原List。5. 性能優(yōu)化與最佳實踐5.1 容量預(yù)分配當(dāng)你知道大概的元素數(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在我的性能測試中處理10萬個元素時預(yù)分配容量比不預(yù)分配快約30%。5.2 避免頻繁的Add操作對于大量數(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在極高性能要求的場景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不過在實際項目中除非確實遇到性能瓶頸否則建議優(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)。