C#集合数据去重的5种方式及对比分析

 更新时间:2024年11月29日 08:28:31   作者:追逐时光者  
今天我们一起来讨论一下关于C#集合数据去重的5种方式并且使用BenchmarkDotNet对这5种方式进行性能基准对比测试分析,每种方法都有其特点和适用场景,我们可以根据具体需求和执行效率选择一种进行使用,需要的朋友可以参考下

BenchmarkDotNet介绍

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

使用HashSet去重

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

        /// <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));
        }

使用循环遍历去重

        /// <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。

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

        /// <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));
        }

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

        /// <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种集合去重的方式进行性能基准对比测试分析。

测试代码

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();
            }
        }
    }
}

分析生成的报告

MethodMeanErrorStdDevGen0Gen1Gen2Allocated
HashSetDuplicate7.043 ms0.0546 ms0.0511 ms343.7500343.7500343.750018169.63 KB
LoopTraversalDuplicate7.385 ms0.0309 ms0.0274 ms---1.16 KB
DistinctDuplicate7.034 ms0.0497 ms0.0465 ms343.7500343.7500343.750018170.1 KB
GroupByDuplicate12.685 ms0.1025 ms0.0958 ms2265.62501781.2500515.625012843.65 KB
CustomEqualityComparerDuplicate25.608 ms0.1826 ms0.1708 ms3812.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 秒)。

以上就是C#集合数据去重的5种方式及对比分析的详细内容,更多关于C#集合数据去重的资料请关注脚本之家其它相关文章!

相关文章

  • C#使用linq计算执行元素在列表中出现次数的方法

    C#使用linq计算执行元素在列表中出现次数的方法

    这篇文章主要介绍了C#使用linq计算执行元素在列表中出现次数的方法,涉及C#使用linq扩展进行列表查询的技巧,需要的朋友可以参考下
    2015-04-04
  • C#匿名委托与Lambda表达式详解

    C#匿名委托与Lambda表达式详解

    这篇文章主要为大家详细介绍了C#匿名委托与Lambda表达式的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • C#遍历文件夹后上传文件夹中所有文件错误案例分析

    C#遍历文件夹后上传文件夹中所有文件错误案例分析

    这篇文章主要介绍了C#遍历文件夹后上传文件夹中所有文件的实现方法,需要的朋友可以参考下
    2015-10-10
  • c# Newtonsoft.Json 常用方法总结

    c# Newtonsoft.Json 常用方法总结

    这篇文章主要介绍了c# Newtonsoft.Json 常用方法的相关资料,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-02-02
  • C#中Equality和Identity浅析

    C#中Equality和Identity浅析

    这篇文章主要介绍了C#中Equality和Identity浅析,本文先是讲解了Equality和Identity的定义,同时讲解了判断两个对象等价性的4种方法,需要的朋友可以参考下
    2014-12-12
  • c#生成缩略图的实现方法

    c#生成缩略图的实现方法

    c#生成缩略图的实现方法,需要的朋友可以参考一下
    2013-04-04
  • unity 鼠标移入弹出UI的操作

    unity 鼠标移入弹出UI的操作

    这篇文章主要介绍了unity 鼠标移入弹出UI的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • WCF的异常处理

    WCF的异常处理

    这篇文章介绍了WCF处理异常的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C#实现网络小程序的步骤详解

    C#实现网络小程序的步骤详解

    经常要检测某些IP地址范围段的计算机是否在线。有很多的方法,比如进入到网关的交换机上去查询、使用现成的工具或者编写一个简单的DOS脚本等等,这些都比较容易实现。本文将用C#来实现,感兴趣的可以了解一下
    2022-12-12
  • C#中HashTable的定义与使用方法

    C#中HashTable的定义与使用方法

    Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对,所以Hashtable可以支持任何类型的keyvalue键值对
    2012-12-12

最新评论