使用Linq求和方法Sum計算集合中多個元素和時應該注意的性能問題

使用Linq求和方法Sum計算集合中多個元素和時應該注意的性能問題

三五月兒 2014-09-10 22:40:31 21633 收藏 2
分類專欄: C# 文章標籤: Linq Sum Linq性能 Linq求和
版權
提出問題

本文使用下面的實例來說明問題,以下是實例的完整代碼。

//************************************************************
//
// Sum應用示例代碼
//
// Author:三五月兒
//
// Date:2014/09/10
//
// http://blog.csdn.net/yl2isoft
//
//************************************************************
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace LinqSumExp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("數據準備中,請稍後...");

List<Score> scoreList = CreateScoreList();

Console.WriteLine("正在執行中,請稍後...");

Stopwatch sw1 = new Stopwatch();
sw1.Start();
//------------代碼片段1--------------------start
int mathScoreSum1 = 0;
int chineseScoreSum1 = 0;
int engLishScoreSum1 = 0;
int physicsScoreSum1 = 0;
int chemistryScoreSum1 = 0;
int biologyScoreSum1 = 0;
foreach (var s in scoreList)
{
mathScoreSum1 += s.MathScore;
chineseScoreSum1 += s.ChineseScore;
engLishScoreSum1 += s.EngLishScore;
physicsScoreSum1 += s.PhysicsScore;
chemistryScoreSum1 += s.ChemistryScore;
biologyScoreSum1 += s.BiologyScore;
}
//------------代碼片段1--------------------end
sw1.Stop();
TimeSpan ts1 = sw1.Elapsed;
Console.WriteLine("代碼片段1的執行時間爲:" + ts1.TotalMilliseconds);

Stopwatch sw2 = new Stopwatch();
sw2.Start();
//------------代碼片段2--------------------start
int mathScoreSum2 = 0;
int chineseScoreSum2 = 0;
int engLishScoreSum2 = 0;
int physicsScoreSum2 = 0;
int chemistryScoreSum2 = 0;
int biologyScoreSum2 = 0;
mathScoreSum2 = scoreList.Sum(it => it.MathScore);
chineseScoreSum2 = scoreList.Sum(it => it.ChineseScore);
engLishScoreSum2 = scoreList.Sum(it => it.EngLishScore);
physicsScoreSum2 = scoreList.Sum(it => it.PhysicsScore);
chemistryScoreSum2 = scoreList.Sum(it => it.ChemistryScore);
biologyScoreSum2 = scoreList.Sum(it => it.BiologyScore);
//------------代碼片段2--------------------end
sw2.Stop();
TimeSpan ts2 = sw2.Elapsed;
Console.WriteLine("代碼片段2的執行時間爲:" + ts2.TotalMilliseconds);
}
static List<Score> CreateScoreList()
{
List<Score> scoreList = new List<Score>();
Random rd = new Random();
for (int i = 0; i < 100; i++)
{
Score s = new Score();
s.StudentId = i;
s.StudentName = "s" + i.ToString();
s.MathScore = rd.Next(0, 100);
s.ChineseScore = rd.Next(0, 100);
s.EngLishScore = rd.Next(0, 100);
s.PhysicsScore = rd.Next(0, 100);
s.ChemistryScore = rd.Next(0, 100);
s.BiologyScore = rd.Next(0, 100);
scoreList.Add(s);
}
return scoreList;
}
}
public class Score
{
public int StudentId { get; set; }
public string StudentName { get; set; }
public int MathScore { get; set; }
public int ChineseScore { get; set; }
public int EngLishScore { get; set; }
public int PhysicsScore { get; set; }
public int ChemistryScore { get; set; }
public int BiologyScore { get; set; }
}
}
實例中先定義Score類,使用Score類來保存學生各門功課的成績,其中屬性MathScore、ChineseScore、EngLishScore、PhysicsScore、ChemistryScore、BiologyScore分別用來保存數學、語文、英語、物理、化學、生物的成績。接着,在CreateScoreList方法中生成包含100個Score對象的集合。最後,使用代碼片段1和代碼片段2來計算集合中各門功課的總和,其中,代碼片段1通過遍歷集合的方法來求和,而代碼片段2使用Linq的求和方法Sum來實現求和。很顯然,兩種方法都可以完成求和這個基本功能。但是,在實際開發中,很多時候除了實現基本功能外,還需要考慮其他許多東西,比如性能。那麼,這裏我就弱弱的問一句:那種方法性能更好?
 

答案揭曉

大家請看黑板。(呵呵,是不是好黑好黑的一塊板子啊)

 

圖1 程序運行結果圖

從程序的執行結果來看,方法1的性能更好。

你可能會說,僅僅通過一次結果無法得出這個結論,因爲偶然性。

爲了讓你心服口服,那我就繼續執行,執行,再執行。
經過我n多次重複試驗(n到底有多大,你猜),發現:每一次都是方法1耗時更少,方法1性能好於方法2。

爲了讓我們的實驗更具有說服力,增加數據量爲1000,10000,100000來執行程序,下面是實驗結果:

1000次:方法1--1.2628;方法2--3.3205
10000次:方法1--3.1866;方法2--8.8877
100000次:方法1--15.3749;方法2--65.5758
還是方法1耗時更少吧?

你要是還不服,那我也沒辦法了,反正我是相信這個結果了。

那麼爲什麼會有這個結果呢?

 

原因說明

查看Linq求和方法Sum的源碼,代碼如下所示:

public static int Sum(this IEnumerable<int> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
int num = 0;
foreach (int num2 in source)
{
num += num2;
}
return num;
}
很顯然,每調用一次Linq的求和方法都會遍歷一次集合,所以,方法2會遍歷集合5次,而方法1只需遍歷集合1次,這就是原因所在。

當然,需要求和的字段越多,數據量越大,兩種方法的性能差距將越大。其實,除了在使用Linq的求和方法Sum時會遇見這個問題外,在使用Linq中其他擴展方法時也會遇到這種問題,希望大家以後注意了。

 
————————————————
版權聲明:本文爲CSDN博主「三五月兒」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/yl2isoft/article/details/39188641

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章