LINQリング:巨大なコレクションのAny()とContains()


103

オブジェクトの膨大なコレクションがある場合、次の間にパフォーマンスの違いはありますか?

Collection.Contains

myCollection.Contains(myElement)

Enumerable.Any

myCollection.Any(currentElement => currentElement == myElement)

7
10000.000 intのコレクション。勝者は300%の包含です。ただし、以下で説明する差異を考慮することは価値があります。
SDReyes 2010

1
これは、2つの間の明確なコントラストを示しているようです:thedailywtf.com/Articles/State-of-the-UNION.aspx
David Peterson

回答:


143

Contains()インスタンスメソッドであり、そのパフォーマンスはコレクション自体に大きく依存します。たとえば、Contains()a ListはO(n)、Contains()a HashSetはO(1)です。

Any()は拡張メソッドであり、すべてのオブジェクトにデリゲートを適用して、コレクションを単純に処理します。したがって、O(n)の複雑さを持ちます。

Any()ただし、デリゲートを渡すことができるため、より柔軟です。Contains()オブジェクトのみを受け入れることができます。


27
Containsに対する拡張メソッドでもありますIEnumerable<T>(ただし、一部のコレクションには独自のContainsインスタンスメソッドもあります)。あなたが言うように、カスタム述語を渡すことができるためAnyよりも柔軟性ContainsContains ありますが、各要素に対してデリゲート呼び出しを実行する必要がないため、わずかに高速かもしれません。
LukeH 2010

1
ない任意の()コレクション内のすべてのオブジェクトに対して操作を実行するか、それが最初のマッチで終了していますか?
クォークリー

1
少なくともソースよると、最初の一致で停止します。All()同様に動作します。
エティエンヌデマルテル

13

コレクションによって異なります。順序付けられたコレクションがある場合Containsは、スマート検索(バイナリ、ハッシュ、bツリーなど)を実行できますが、 `Any()を使用すると、基本的に、それが見つかるまで列挙し続けます(LINQ-to-Objectsを想定)。 。

また、例でAny()==、参照の等価性をチェックする演算子を使用しているのに対し、オーバーライドされる可能性のあるまたはメソッドContainsを使用していることにも注意してください。IEquatable<T>Equals()


4
.Anyを使用すると、プロパティを簡単に比較できます。.Containsを使用すると、オブジェクトを比較するだけで、プロパティを比較するために追加のIEqualityComparerが必要になります。
msfanboy

1
@msfanboy:それは本当ですが、問題は特にパフォーマンスに関するものであり、オブジェクト全体の比較を示しました。だからここでは関係ないと思います。
tster

4

それは実装myCollection方法を決定するContains()isのタイプに依存すると思います。たとえば、ソートされたバイナリツリーであれば、より賢く検索できます。また、要素のハッシュを考慮に入れる場合もあります。 Any()一方、条件を満たす最初の要素が見つかるまで、コレクションを列挙します。オブジェクトがよりスマートな検索メソッドを持つかどうかの最適化はありません。


0

Contains()も、正しい方法で使用すると高速に動作する拡張メソッドです。例:

var result = context.Projects.Where(x => lstBizIds.Contains(x.businessId)).Select(x => x.projectId).ToList();

これはクエリを与えます

SELECT Id FROM Projects INNER JOIN (VALUES (1), (2), (3), (4), (5)) AS Data(Item) ON Projects.UserId = Data.Item

一方、Any()は常にO(n)を反復処理します。

これがうまくいくことを願っています...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.