.NET高效實現(xiàn)List集合去重的多種方法詳解
在 .NET 開發(fā)中,處理集合數(shù)據(jù)時經(jīng)常會遇到需要對 List<T> 進行去重的場景。無論是基本類型(如 int、string)還是自定義對象,.NET 提供了多種簡潔高效的去重方式。本文將系統(tǒng)介紹幾種常用且性能良好的去重方法,并對比其適用場景。
一、使用 LINQ 的 Distinct() 方法(最常用)
LINQ 提供了最簡潔的去重方式:Distinct() 擴展方法。
1. 基本類型去重
var numbers = new List<int> { 1, 2, 2, 3, 4, 4, 5 };
var uniqueNumbers = numbers.Distinct().ToList();
// 結果: [1, 2, 3, 4, 5]
2. 自定義對象去重(需實現(xiàn) IEqualityComparer 或重寫 Equals/GetHashCode)
若直接對自定義類調(diào)用 Distinct(),默認比較的是引用(除非重寫了 Equals 和 GetHashCode)。
方式 A:重寫 Equals 和 GetHashCode
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public override bool Equals(object obj) => obj is Person p && Name == p.Name && Age == p.Age;
public override int GetHashCode() => HashCode.Combine(Name, Age);
}
var people = new List<Person>
{
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Bob", Age = 25 }
};
var uniquePeople = people.Distinct().ToList(); // 自動去重
方式 B:使用自定義 IEqualityComparer
public class PersonNameComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y) => x?.Name == y?.Name;
public int GetHashCode(Person obj) => obj?.Name?.GetHashCode() ?? 0;
}
var uniqueByName = people.Distinct(new PersonNameComparer()).ToList();
二、使用 HashSet(高性能推薦)
HashSet<T> 天然具有去重特性,插入時自動忽略重復項,性能優(yōu)于 Distinct()(尤其在大數(shù)據(jù)量時)。
var numbers = new List<int> { 1, 2, 2, 3, 4, 4, 5 };
var uniqueNumbers = new HashSet<int>(numbers).ToList();
對于自定義對象,同樣需要提供合適的 IEqualityComparer<T>:
var uniquePeople = new HashSet<Person>(people, new PersonNameComparer()).ToList();
優(yōu)點:時間復雜度接近 O(n),適合頻繁去重或大數(shù)據(jù)集。
注意:HashSet 不保證元素順序(但 .NET Core 6+ 的 HashSet 在某些情況下保持插入順序,不建議依賴此行為)。
三、使用 ToLookup / GroupBy(按條件去重)
如果需要“保留第一個出現(xiàn)的元素”并按特定字段去重,可結合 GroupBy:
var uniquePeople = people
.GroupBy(p => p.Name)
.Select(g => g.First())
.ToList();
這種方式靈活,適用于復雜去重邏輯(如保留最新記錄、按多個字段分組等)。
四、.NET 6+ 新特性:DistinctBy()
從 .NET 6 開始,LINQ 新增了 DistinctBy() 方法,無需實現(xiàn)比較器即可按屬性去重:
var uniquePeople = people.DistinctBy(p => p.Name).ToList();
// 或按多個屬性
var uniqueByBoth = people.DistinctBy(p => new { p.Name, p.Age }).ToList();
強烈推薦:代碼簡潔、語義清晰、性能良好,是現(xiàn)代 .NET 項目的首選方案。
五、性能與選型建議
| 方法 | 適用場景 | 是否保序 | 性能 | .NET 版本要求 |
|---|---|---|---|---|
| Distinct() | 簡單去重,已重寫 Equals/GetHashCode | 是 | 中等 | 所有版本 |
| HashSet<T> | 大數(shù)據(jù)量、高頻去重 | 否(通常) | 高 | 所有版本 |
| GroupBy + First | 按條件去重、需控制保留邏輯 | 是 | 中等 | 所有版本 |
| DistinctBy() | 按屬性去重、代碼簡潔 | 是 | 高 | .NET 6+ |
總結
對于 基本類型,直接使用 Distinct() 即可。
對于 自定義對象:
- 若使用 .NET 6 及以上,優(yōu)先使用
DistinctBy(); - 若需兼容舊版本,可選擇
GroupBy或實現(xiàn)IEqualityComparer<T>; - 若追求極致性能且不關心順序,使用
HashSet<T>。
合理選擇去重方式,不僅能提升代碼可讀性,還能顯著優(yōu)化程序性能。希望本文能幫助你在 .NET 項目中高效處理集合去重問題!
到此這篇關于.NET高效實現(xiàn)List集合去重的多種方法詳解的文章就介紹到這了,更多相關.NET List集合去重內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
.Net通過TaskFactory.FromAsync簡化APM
這篇文章介紹了.Net通過TaskFactory.FromAsync簡化APM的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06
asp.net 驗證字符串是否為純數(shù)字檢測函數(shù)
如何驗證字符串是否為純數(shù)字2010-03-03
Visual studio 2017如何發(fā)布dotnet core到docker
這篇文章主要介紹了Visual studio 2017如何發(fā)布dotnet core到docker的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04

