.NET高效实现List集合去重的多种方法详解
在 .NET 开发中,处理集合数据时经常会遇到需要对 List<T> 进行去重的场景。无论是基本类型(如 int、string)还是自定义对象,.NET 提供了多种简洁高效的去重方式。本文将系统介绍几种常用且性能良好的去重方法,并对比其适用场景。
一、使用 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. 自定义对象去重(需实现 IEqualityComparer 或重写 Equals/GetHashCode)
若直接对自定义类调用 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> 天然具有去重特性,插入时自动忽略重复项,性能优于 Distinct()(尤其在大数据量时)。
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();
优点:时间复杂度接近 O(n),适合频繁去重或大数据集。
注意:HashSet 不保证元素顺序(但 .NET Core 6+ 的 HashSet 在某些情况下保持插入顺序,不建议依赖此行为)。
三、使用 ToLookup / GroupBy(按条件去重)
如果需要“保留第一个出现的元素”并按特定字段去重,可结合 GroupBy:
var uniquePeople = people
.GroupBy(p => p.Name)
.Select(g => g.First())
.ToList();
这种方式灵活,适用于复杂去重逻辑(如保留最新记录、按多个字段分组等)。
四、.NET 6+ 新特性:DistinctBy()
从 .NET 6 开始,LINQ 新增了 DistinctBy() 方法,无需实现比较器即可按属性去重:
var uniquePeople = people.DistinctBy(p => p.Name).ToList();
// 或按多个属性
var uniqueByBoth = people.DistinctBy(p => new { p.Name, p.Age }).ToList();
强烈推荐:代码简洁、语义清晰、性能良好,是现代 .NET 项目的首选方案。
五、性能与选型建议
| 方法 | 适用场景 | 是否保序 | 性能 | .NET 版本要求 |
|---|---|---|---|---|
| Distinct() | 简单去重,已重写 Equals/GetHashCode | 是 | 中等 | 所有版本 |
| HashSet<T> | 大数据量、高频去重 | 否(通常) | 高 | 所有版本 |
| GroupBy + First | 按条件去重、需控制保留逻辑 | 是 | 中等 | 所有版本 |
| DistinctBy() | 按属性去重、代码简洁 | 是 | 高 | .NET 6+ |
总结
对于 基本类型,直接使用 Distinct() 即可。
对于 自定义对象:
- 若使用 .NET 6 及以上,优先使用
DistinctBy(); - 若需兼容旧版本,可选择
GroupBy或实现IEqualityComparer<T>; - 若追求极致性能且不关心顺序,使用
HashSet<T>。
合理选择去重方式,不仅能提升代码可读性,还能显著优化程序性能。希望本文能帮助你在 .NET 项目中高效处理集合去重问题!
到此这篇关于.NET高效实现List集合去重的多种方法详解的文章就介绍到这了,更多相关.NET List集合去重内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
asp.net Mvc4 使用ajax结合分页插件实现无刷新分页
本篇文章主要介绍了 asp.net Mvc4 使用ajax结合分页插件实现无刷新分页,ajax通过回调函数把控制器返回的分部视图内容加载到主视图中显示,有兴趣的可以了解一下。2017-01-01
ASP.NET中在一般处理程序中使用session的简单介绍
这篇文章介绍了ASP.NET中在一般处理程序中使用session,有需要的朋友可以参考一下2013-10-10
ASP.NET Core依赖注入系列教程之控制反转(IoC)
这篇文章主要给大家介绍了关于ASP.NET Core依赖注入系列教程之控制反转(IoC)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2018-11-11


最新评论