首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C#集合数据去重的5种方式及其性能对比测试分析

C#集合数据去重的5种方式及其性能对比测试分析

作者头像
郑子铭
发布2025-01-03 20:45:53
发布2025-01-03 20:45:53
39400
代码可运行
举报
运行总次数:0
代码可运行

前言

今天我们一起来讨论一下关于C#集合数据去重的5种方式并且使用BenchmarkDotNet对这5种方式进行性能基准对比测试分析,每种方法都有其特点和适用场景,我们可以根据具体需求和执行效率选择一种进行使用。

BenchmarkDotNet介绍

BenchmarkDotNet是一个基于.NET开源、功能全面、易于使用的性能基准测试框架,它为.NET开发者提供了强大的性能评估和优化能力。通过自动化测试、多平台支持、高级统计分析和自定义配置等特性,BenchmarkDotNet帮助开发者更好地理解和优化软件系统的性能表现。

使用HashSet去重

C# 中的 HashSet 是一种集合类型,它确保其中的元素是唯一的,不允许重复值的存在。当你尝试向 HashSet 中添加一个重复的元素时,HashSet 会忽略重复的值,而不会引发错误。这使得 HashSet 成为一个非常方便的数据结构,用于存储一组唯一的元素,并且在需要时可以高效地进行查找、插入和删除操作,注意HashSet中的元素是无序的。

代码语言:javascript
代码运行次数:0
运行
复制
        /// <summary>
        /// 使用HashSet去重
        /// TODO:HashSet是一个集合类,它的特点是不允许重复元素,可以方便地实现去重功能。
        /// </summary>
        public static void HashSetDuplicate()
        {
            var dataSource = new List<int>() { 1, 2, 3, 2, 5, 88, 99, 99, 100, 88, 30, 50, 15, 100, 99, 99, 2, 3 };
            HashSet<int> uniqueData = new HashSet<int>(dataSource);

            Console.WriteLine(string.Join(", ", uniqueData));
        }

使用循环遍历去重

代码语言:javascript
代码运行次数:0
运行
复制
        /// <summary>
        /// 直接循环遍历去重
        /// </summary>
        public static void LoopTraversalDuplicate()
        {
            var dataSource = new List<int>() { 1, 2, 3, 2, 5, 88, 99, 99, 100, 88, 30, 50, 15, 100, 99, 99, 2, 3 };
            var uniqueData = new List<int>();
            foreach (var item in dataSource)
            {
                //if (!uniqueData.Any(x => x == item))
                //if (!uniqueData.Exists(x => x == item))
                if (!uniqueData.Contains(item))
                {
                    uniqueData.Add(item);
                }
            }
            Console.WriteLine(string.Join(", ", uniqueData));
        }

使用Linq的Distinct()方法去重

Linq中的Distinct()方法用于从集合中筛选出不重复的元素。Distinct()方法基于元素的相等性来进行筛选,并返回一个包含不重复元素的新序列。底层实现还是使用到了HashSet。

代码语言:javascript
代码运行次数:0
运行
复制
        /// <summary>
        /// 使用Linq的Distinct()方法去重
        /// </summary>
        public static void DistinctDuplicate()
        {
            var dataSource = new List<int>() { 1, 2, 3, 2, 5, 88, 99, 99, 100, 88, 30, 50, 15, 100, 99, 99, 2, 3 };
            var uniqueData = dataSource.Distinct().ToList();

            Console.WriteLine(string.Join(", ", uniqueData));
        }

使用Linq的GroupBy()方法去重

GroupBy()方法将原始集合中的元素进行分组,根据指定的键或条件进行分组。每个分组都会有一个唯一的键,通过将原始集合分组并选择每个分组中的第一个元素,实现了去重的效果。

代码语言:javascript
代码运行次数:0
运行
复制
        /// <summary>
        /// 使用Linq的GroupBy()方法去重
        /// </summary>
        public static void GroupByDuplicate()
        {
            var dataSource = new List<int>() { 1, 2, 3, 2, 5, 88, 99, 99, 100, 88, 30, 50, 15, 100, 99, 99, 2, 3 };

            //GroupBy()方法将原始集合中的元素进行分组,根据指定的键或条件进行分组。每个分组都会有一个唯一的键,通过将原始集合分组并选择每个分组中的第一个元素,实现了去重的效果。
            var uniqueData = dataSource.GroupBy(item => item).Select(group => group.First()).ToList();

            Console.WriteLine(string.Join(", ", uniqueData));
        }

使用自定义的比较器和循环遍历

代码语言:javascript
代码运行次数:0
运行
复制
        /// <summary>
        /// 使用自定义的比较器和循环遍历
        /// </summary>
        public static void CustomEqualityComparerDuplicate()
        {
            var dataSource = new List<int>() { 1, 2, 3, 2, 5, 88, 99, 99, 100, 88, 30, 50, 15, 100, 99, 99, 2, 3 };
            var uniqueData = new List<int>();
            foreach (var item in dataSource)
            {
                if (!uniqueData.Contains(item, new CustomEqualityComparer()))
                {
                    uniqueData.Add(item);
                }
            }
            Console.WriteLine(string.Join(", ", uniqueData));
        }

        /// <summary>
        /// 自定义的比较器
        /// </summary>
        public class CustomEqualityComparer : IEqualityComparer<int>
        {
            public bool Equals(int x, int y)
            {
                return x == y;
            }

            public int GetHashCode(int obj)
            {
                return obj.GetHashCode();
            }
        }

性能基准对比测试分析

接下来我们使用BenchmarkDotNet对这5种集合去重的方式进行性能基准对比测试分析。

测试代码

代码语言:javascript
代码运行次数:0
运行
复制
using BenchmarkDotNet.Attributes;

namespace BenchmarkDotNetExercise
{
    [MemoryDiagnoser]//记录内存分配情况
    public class DataSetDeduplicationBenchmark
    {
        private List<int> dataSource;

        public DataSetDeduplicationBenchmark()
        {
            // 生成大量重复数据  
            dataSource = Enumerable.Repeat(Enumerable.Range(1, 100), 10000).SelectMany(x => x).ToList();
        }

        /// <summary>
        /// 使用HashSet去重
        /// TODO:HashSet是一个集合类,它的特点是不允许重复元素,可以方便地实现去重功能。
        /// </summary>
        [Benchmark]
        public void HashSetDuplicate()
        {
            HashSet<int> uniqueData = new HashSet<int>(dataSource);
        }

        /// <summary>
        /// 直接循环遍历去重
        /// </summary>
        [Benchmark]
        public void LoopTraversalDuplicate()
        {
            var uniqueData = new List<int>();
            foreach (var item in dataSource)
            {
                //if (!uniqueData.Any(x => x == item))
                //if (!uniqueData.Exists(x => x == item))
                if (!uniqueData.Contains(item))
                {
                    uniqueData.Add(item);
                }
            }
        }

        /// <summary>
        /// 使用Linq的Distinct()方法去重
        /// </summary>
        [Benchmark]
        public void DistinctDuplicate()
        {
            var uniqueData = dataSource.Distinct().ToList();
        }

        /// <summary>
        /// 使用Linq的GroupBy()方法去重
        /// </summary>
        [Benchmark]
        public void GroupByDuplicate()
        {
            //GroupBy()方法将原始集合中的元素进行分组,根据指定的键或条件进行分组。每个分组都会有一个唯一的键,通过将原始集合分组并选择每个分组中的第一个元素,实现了去重的效果。
            var uniqueData = dataSource.GroupBy(item => item).Select(group => group.First()).ToList();
        }

        /// <summary>
        /// 使用自定义的比较器和循环遍历
        /// </summary>
        [Benchmark]
        public void CustomEqualityComparerDuplicate()
        {
            var uniqueData = new List<int>();
            foreach (var item in dataSource)
            {
                if (!uniqueData.Contains(item, new CustomEqualityComparer()))
                {
                    uniqueData.Add(item);
                }
            }
        }

        /// <summary>
        /// 自定义的比较器
        /// </summary>
        public class CustomEqualityComparer : IEqualityComparer<int>
        {
            public bool Equals(int x, int y)
            {
                return x == y;
            }

            public int GetHashCode(int obj)
            {
                return obj.GetHashCode();
            }
        }
    }
}

分析生成的报告

Method

Mean

Error

StdDev

Gen0

Gen1

Gen2

Allocated

HashSetDuplicate

7.043 ms

0.0546 ms

0.0511 ms

343.7500

343.7500

343.7500

18169.63 KB

LoopTraversalDuplicate

7.385 ms

0.0309 ms

0.0274 ms

-

-

-

1.16 KB

DistinctDuplicate

7.034 ms

0.0497 ms

0.0465 ms

343.7500

343.7500

343.7500

18170.1 KB

GroupByDuplicate

12.685 ms

0.1025 ms

0.0958 ms

2265.6250

1781.2500

515.6250

12843.65 KB

CustomEqualityComparerDuplicate

25.608 ms

0.1826 ms

0.1708 ms

3812.5000

-

-

23438.68 KB

说明:

  • Mean: 所有测量值的算术平均值。
  • Error: 99.9% 置信区间的一半。
  • StdDev: 所有测量值的标准差。
  • Gen0: 第 0 代 GC 每 1000 次操作收集一次。
  • Gen1: 第 1 代 GC 每 1000 次操作收集一次。
  • Gen2: 第 2 代 GC 每 1000 次操作收集一次。
  • Allocated: 每次操作分配的内存(仅托管内存,包含所有内容,1KB = 1024B)。
  • 1 ms: 1 毫秒(0.001 秒)
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-01-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • BenchmarkDotNet介绍
  • 使用HashSet去重
  • 使用循环遍历去重
  • 使用Linq的Distinct()方法去重
  • 使用Linq的GroupBy()方法去重
  • 使用自定义的比较器和循环遍历
  • 性能基准对比测试分析
    • 测试代码
    • 分析生成的报告
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档