.NET高效實(shí)現(xiàn)List集合去重的多種方法詳解
在 .NET 開發(fā)中,處理集合數(shù)據(jù)時經(jīng)常會遇到需要對 List<T> 進(jìn)行去重的場景。無論是基本類型(如 int、string)還是自定義對象,.NET 提供了多種簡潔高效的去重方式。本文將系統(tǒng)介紹幾種常用且性能良好的去重方法,并對比其適用場景。
一、使用 LINQ 的 Distinct() 方法(最常用)
LINQ 提供了最簡潔的去重方式:Distinct() 擴(kuò)展方法。
1. 基本類型去重
var numbers = new List<int> { 1, 2, 2, 3, 4, 4, 5 };
var uniqueNumbers = numbers.Distinct().ToList();
// 結(jié)果: [1, 2, 3, 4, 5]
2. 自定義對象去重(需實(shí)現(xiàn) IEqualityComparer 或重寫 Equals/GetHashCode)
若直接對自定義類調(diào)用 Distinct(),默認(rèn)比較的是引用(除非重寫了 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> 天然具有去重特性,插入時自動忽略重復(fù)項(xiàng),性能優(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)點(diǎn):時間復(fù)雜度接近 O(n),適合頻繁去重或大數(shù)據(jù)集。
注意:HashSet 不保證元素順序(但 .NET Core 6+ 的 HashSet 在某些情況下保持插入順序,不建議依賴此行為)。
三、使用 ToLookup / GroupBy(按條件去重)
如果需要“保留第一個出現(xiàn)的元素”并按特定字段去重,可結(jié)合 GroupBy:
var uniquePeople = people
.GroupBy(p => p.Name)
.Select(g => g.First())
.ToList();
這種方式靈活,適用于復(fù)雜去重邏輯(如保留最新記錄、按多個字段分組等)。
四、.NET 6+ 新特性:DistinctBy()
從 .NET 6 開始,LINQ 新增了 DistinctBy() 方法,無需實(shí)現(xiàn)比較器即可按屬性去重:
var uniquePeople = people.DistinctBy(p => p.Name).ToList();
// 或按多個屬性
var uniqueByBoth = people.DistinctBy(p => new { p.Name, p.Age }).ToList();
強(qiáng)烈推薦:代碼簡潔、語義清晰、性能良好,是現(xiàn)代 .NET 項(xiàng)目的首選方案。
五、性能與選型建議
| 方法 | 適用場景 | 是否保序 | 性能 | .NET 版本要求 |
|---|---|---|---|---|
| Distinct() | 簡單去重,已重寫 Equals/GetHashCode | 是 | 中等 | 所有版本 |
| HashSet<T> | 大數(shù)據(jù)量、高頻去重 | 否(通常) | 高 | 所有版本 |
| GroupBy + First | 按條件去重、需控制保留邏輯 | 是 | 中等 | 所有版本 |
| DistinctBy() | 按屬性去重、代碼簡潔 | 是 | 高 | .NET 6+ |
總結(jié)
對于 基本類型,直接使用 Distinct() 即可。
對于 自定義對象:
- 若使用 .NET 6 及以上,優(yōu)先使用
DistinctBy(); - 若需兼容舊版本,可選擇
GroupBy或?qū)崿F(xiàn)IEqualityComparer<T>; - 若追求極致性能且不關(guān)心順序,使用
HashSet<T>。
合理選擇去重方式,不僅能提升代碼可讀性,還能顯著優(yōu)化程序性能。希望本文能幫助你在 .NET 項(xiàng)目中高效處理集合去重問題!
到此這篇關(guān)于.NET高效實(shí)現(xiàn)List集合去重的多種方法詳解的文章就介紹到這了,更多相關(guān).NET List集合去重內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
asp.net Mvc4 使用ajax結(jié)合分頁插件實(shí)現(xiàn)無刷新分頁
本篇文章主要介紹了 asp.net Mvc4 使用ajax結(jié)合分頁插件實(shí)現(xiàn)無刷新分頁,ajax通過回調(diào)函數(shù)把控制器返回的分部視圖內(nèi)容加載到主視圖中顯示,有興趣的可以了解一下。2017-01-01
vb 中的MD5加密在asp.net中的實(shí)現(xiàn)
給定標(biāo)識哈希類型的密碼和字符串,該例程產(chǎn)生一個適合存儲在配置文件中的哈希密碼,感興趣的朋友可以參考下本文2013-04-04
ASP.NET中在一般處理程序中使用session的簡單介紹
這篇文章介紹了ASP.NET中在一般處理程序中使用session,有需要的朋友可以參考一下2013-10-10
ASP.NET Core依賴注入系列教程之控制反轉(zhuǎn)(IoC)
這篇文章主要給大家介紹了關(guān)于ASP.NET Core依賴注入系列教程之控制反轉(zhuǎn)(IoC)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11
ASP.NET?Core中創(chuàng)建中間件的方式匯總
ASP.NET?Core中間件(Middleware)是用于處理HTTP請求和響應(yīng)的組件,它們被安排在請求處理管道中,并按順序執(zhí)行,這篇文章主要介紹了ASP.NET?Core中創(chuàng)建中間件的幾種方式,需要的朋友可以參考下2024-07-07

