一、性能测试
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
// 生成测试数据
Random rand = new Random();
List<int> list1 = Enumerable.Range(0, 100000).Select(_ => rand.Next(0, 200000)).ToList();
List<int> list2 = Enumerable.Range(0, 100000).Select(_ => rand.Next(0, 200000)).ToList();
// 双循环测试
Stopwatch sw1 = Stopwatch.StartNew();
var result1 = new List<int>();
foreach (var item in list1)
{
if (list2.Contains(item))
{ // 优化后的Contains检查
result1.Add(item);
}
}
sw1.Stop();
Console.WriteLine("双循环耗时: {0}ms",sw1.ElapsedMilliseconds);
// LINQ Intersect测试
Stopwatch sw2 = Stopwatch.StartNew();
var result2 = list1.Intersect(list2).ToList();
sw2.Stop();
Console.WriteLine("LINQ Intersect耗时: {0}ms", sw2.ElapsedMilliseconds);
}
}
}
测试结果:
双循环:13008ms; intersect:21ms
二、双循环与intersect
1、双循环
时间复杂度:O(n²)
原理:嵌套遍历两个列表,逐个元素比较。
性能:随着数据量的增加,性能急剧下降。
2、intersect
时间复杂度:O(n+m)
原理:内部使用哈希集合(HashSet<T>)存储第二个列表的元素,遍历第一个列表时通过哈希查找(O(1)时间复杂度)判断是否存在。
性能:列表长度达到百万级也能高效处理。
三、结论
- 性能差异:Intersect比双循环快1-2个数量级,尤其在大数据量下。
- 实现原理:
(1)双循环:逐个元素比较,时间复杂度随数据量平方增长。
(2)Intersect:利用哈希集合优化查找,时间复杂度线性增长。
- 代码简洁性:Intersect只需一行代码,双循环需要多层嵌套。
四、注意事项
- 重复元素:Intersect默认去重
- 数据类型:Intersect对引用类型需重写Equals和GetHashCode