Linq中Count 和Any 引發的效率問題

2022-03-03 01:28:45 字數 2825 閱讀 3488

1、count和any

今天看了0 來判斷集合非空" href="" target="_blank">鶴沖天的文章:linq:切勿使用 count() > 0 來判斷集合非空   有所收穫,寫下文章總結一下:

先看如下**:

1

static

void main(string

args)212

public

static ienumerable getnums(int start, int

count)

1318

public

static

void someaction(ienumerablesource)

1925 }

自己除錯了下,當yield迴圈低於100000次的話,count()和any()的執行時間差不多,count()時間略大於any()所耗費的時間,當大於100000次的話,count()執行時間就遠比any()執行時間多很多!例如上面的程式執行結果,count耗時2233毫秒,any卻只耗時3毫秒!這是為什麼呢?我們來看下原因:分別反編譯enumerate.count 的原始碼和enumerate.any的原始碼,如下:

enumerate.any 實現**如下:

1

public

static

bool any(this ienumerablesource)27

using (ienumeratorenumerator =source.getenumerator())813

}14return

false

;15 }

enumerate.count 的原始碼如下:

1

public

static

int count(this ienumerablesource)

27 icollectionis2 = source as icollection;

8if (is2 != null)9

12 icollection is3 = source as

icollection;

13if (is3 != null)14

17int num = 0;18

using (ienumeratorenumerator =source.getenumerator())

1924}25

return

num;

26 }

無論迴圈多少次,any方法執行的時間總是最少的,大概10毫秒之內,我想大家從any的原始碼可以知道這個原因,any方法先判斷集合是否為空,然後判斷集合是否有資料,只進行一次movenext(),並未進行迴圈查詢集合數量!所以耗費的時間當然一直是最少的了!

我們再看count方法,同樣是先進行集合判空操作,然後判斷當前的集合source是否能轉成icollection型別,如果能轉成,就直接返回此集合的count屬性,不會在進行下面的迴圈獲取集合個數的操作了,為什麼count()方法比any()方法執行的時間長呢?答案就在於此:因為getnums方法中用yield返回純粹的ienumerable型別,但是icollection是繼承自ienumerable型別的,所以必然不好被轉換,也就是count()原始碼中的下面**不會執行

icollection is3 = source as

icollection;

if (is3 != null

)

上面的**不會執行,那麼必然會進行下面的**操作,也就是迴圈獲取集合的個數:

int num = 0

;

using (ienumeratorenumerator =source.getenumerator())

}return num;

這樣必然會導致count()方法耗時很久!

2、如果我們把getnums進行如下修改,其他**不動:

public

static ienumerable getnums(int start, int

count)

這時我們在執行程式,可以看到無論迴圈次數多少,count和any兩者執行的時間差不多,大概是1315毫秒左右,其中1312毫秒用於list集合的裝填工作,3毫秒用於count或any的判斷時間,為什麼會出現這種情況呢,我想通過上面大家都知道了,因為此時getnums方法返回的是list型別,此型別繼承於icollection,所以必然可以被轉換,就會返回此型別的count屬性,count 方法對 icollection 進行了優化,直接訪返回它的 count 屬性,也就是返回乙個數,當然很快了,下面的迴圈獲取集合的個數當然也就不會執行了,也就節約了時間。

3、對某人問題的思考

有人說:」我有個程式裡經常要判集合裡是否僅有乙個元素,又不能用count,

不得已自己寫了個擴充套件方法 bool check(this ienumerablesource, int n), 當讀到第n+1個元素就直接返回false「

我想如果此人用的集合是繼承於icollection的話,例如list,那麼是沒必要對ienumerable進行擴充套件的,通過反編譯count原始碼可以知道,如果集合source可以轉換成icollection的話,是可以直接通過count屬性獲取到集合的總數量的,所以耗費的時間要不了多少,也就沒必要對ienumerable進行擴充套件了!反之,如果不是繼承icollection的話,例如ienumerable,就必須自己擴充套件ienumerable方法了,如果還用count的話,就會造成迴圈了,也就降低了程式的執行效率了!

4、參考

鶴沖天

2013-12-13   21:30:12

matlab 中all和any函式

all函式 檢 測矩陣中是否全為非零元素,如果是,則返回1,否則,返回0。any函式 檢測矩陣中是否有非零元素,如果有,則返回1,否則,返回0。用法和all一樣 語法 b all a b all a,dim 複製 b all a 如果a是乙個向量,如果所有的元素都是非零的,則返回1,如果有乙個元素為...

matlab中all和any用法

all函式 檢測矩陣中是否全為非零元素 any函式 檢測矩陣中是否有非零元素,如果有,則返回1,否則,返回0。用法和all一樣 語法 b all a b all a,dim 複製 b all a 如果a是乙個向量,如果所有的元素都是非零的,則返回1,如果有乙個元素為零,則返回0。如果a是乙個矩陣,則...

python中all 和any 函式總結

這個函式可能會有點坑,解釋如下 如果iterable的所有元素不為0,false或者iterable為空,函式all iterable 返回true,否則返回false。注意 空元組 空列表返回值為true。例項 all a b c d 列表list,元素都不為空或0 true all a b d ...