Linq查找最大值max最小值min效率比较

对linq查找极值的几种方法做一个效率上的比较

// 首先创建了一个10_000_000大小的PointF列表
var rdn = new Random();
var points = Enumerable
    .Range(0, 10_000_000)
    .Select(t =>
        new PointF((float)rdn.NextDouble() * 200, (float)rdn.NextDouble() * 200))
    .ToList();

// 方法一:最小/最大值只排一次序
var sth = new Stopwatch();
sth.Start();
var orderPX = points.OrderBy(t => t.X).ToList();
var orderPY = points.OrderBy(t => t.Y).ToList();
var minX = orderPX.First().X;
var maxX = orderPX.Last().X;
var minY = orderPY.First().Y;
var maxY = orderPY.Last().Y;
Console.WriteLine($"{nameof(minX)}:{minX}, {nameof(maxX)}:{maxX}, {nameof(minY)}:{minY}, {nameof(maxY)}:{maxY}");
Console.WriteLine($"OrderBy:{sth.Elapsed}");

// 方法二:先获取值,在排序
sth.Restart();
var orderX = points.Select(t => t.X).OrderBy(t => t).ToList();
var orderY = points.Select(t => t.Y).OrderBy(t => t).ToList();
minX = orderX.First();
maxX = orderX.Last();
minY = orderY.First();
maxY = orderY.Last();
Console.WriteLine($"{nameof(minX)}:{minX}, {nameof(maxX)}:{maxX}, {nameof(minY)}:{minY}, {nameof(maxY)}:{maxY}");
Console.WriteLine($"Select,OrderBy:{sth.Elapsed}");

// 方法三:最小/最大值分别排序
sth.Restart();
minX = points.OrderBy(t=>t.X).First().X;
maxX = points.OrderByDescending(t=>t.X).First().X;
minY = points.OrderBy(t=>t.Y).First().Y;
maxY = points.OrderByDescending(t=>t.Y).First().Y;
Console.WriteLine($"{nameof(minX)}:{minX}, {nameof(maxX)}:{maxX}, {nameof(minY)}:{minY}, {nameof(maxY)}:{maxY}");
Console.WriteLine($"OrderBy,OrderByDescending:{sth.Elapsed}");


// 方法四:直接使用min/max函数
sth.Restart();
minX = points.Min(t => t.X);
maxX = points.Max(t => t.X);
minY = points.Min(t => t.Y);
maxY = points.Max(t => t.Y);
Console.WriteLine($"{nameof(minX)}:{minX}, {nameof(maxX)}:{maxX}, {nameof(minY)}:{minY}, {nameof(maxY)}:{maxY}");
Console.WriteLine($"min,max:{sth.Elapsed}");

结果如下:

minX:6.938353E-05, maxX:200, minY:1.117587E-05, maxY:200
OrderBy:00:00:14.5413189

minX:6.938353E-05, maxX:200, minY:1.117587E-05, maxY:200
Select,OrderBy:00:00:14.0296968

minX:6.938353E-05, maxX:200, minY:1.117587E-05, maxY:200
Select,OrderBy:00:00:00.8116068

minX:6.938353E-05, maxX:200, minY:1.117587E-05, maxY:200
min,max:00:00:00.5200925

总结:
最快的方法还是linq原生min/max函数 。效率是排序后查找方法一/二的30倍左右,内存需求也更小。方法一和二基本一致,也就是说无论值类型是什么,基本不对排序产生影像。而方法一和三差距如此之大,虽然看上去增加了排序的次数,但效率接近方法四。其原因是在一次完整的linq表达式计算中,内存申请率较低。也就是说,内存写会对算法产生极大的影响。而在四种方法中一和二会对内存写有极大的需求。所以效率最低。

上一篇:遍历数列


下一篇:mybaits源码分析--binding模块(五)