LINQ Ring: Any () vs Contains () für riesige Sammlungen

103

Gibt es bei einer großen Sammlung von Objekten einen Leistungsunterschied zwischen den folgenden?

Sammlung. Enthält :

myCollection.Contains(myElement)

Enumerable.Any :

myCollection.Any(currentElement => currentElement == myElement)
SDReyes
quelle
7
Eine Sammlung von 10'000.000 Ints. Gewinner ist der enthält für 300%. Es lohnt sich jedoch, die unten genannten Abweichungen zu berücksichtigen.
SDReyes
1
Dies scheint einen starken Kontrast zwischen den beiden zu zeigen: thedailywtf.com/Articles/State-of-the-UNION.aspx
David Peterson

Antworten:

143

Contains()ist eine Instanzmethode, deren Leistung weitgehend von der Sammlung selbst abhängt. Zum Beispiel ist Contains()auf a ListO (n), während Contains()auf a HashSetO (1) ist.

Any()ist eine Erweiterungsmethode und geht einfach die Sammlung durch und wendet den Delegaten auf jedes Objekt an. Es hat daher eine Komplexität von O (n).

Any()ist jedoch flexibler, da Sie einen Delegaten übergeben können. Contains()kann nur ein Objekt akzeptieren.

Etienne de Martel
quelle
27
Containsist auch eine Erweiterungsmethode gegen IEnumerable<T>(obwohl einige Sammlungen auch eine eigene ContainsInstanzmethode haben). Wie Sie sagen, Anyist es flexibler als Containsweil Sie ihm ein benutzerdefiniertes Prädikat übergeben können, aber Contains möglicherweise etwas schneller, weil es nicht für jedes Element einen Delegatenaufruf durchführen muss.
LukeH
1
Führt Any () die Operation für alle Objekte in der Sammlung aus oder endet sie mit der ersten Übereinstimmung?
Quarkly
1
Zumindest laut Quelle stoppt es beim ersten Spiel. All()funktioniert ähnlich.
Etienne de Martel
13

Das hängt von der Sammlung ab. Wenn Sie eine geordnete Sammlung haben, führen Sie Containsmöglicherweise eine intelligente Suche durch (Binär, Hash, B-Baum usw.), während Sie bei `Any () grundsätzlich mit der Aufzählung beschäftigt sind, bis Sie sie finden (unter der Annahme von LINQ-to-Objects). .

Beachten Sie auch , dass in Ihrem Beispiel, Any()das unter Verwendung von ==Operator, der für Referenz Gleichheit überprüfen wird, während Containswird verwenden IEquatable<T>oder die Equals()Methode, die außer Kraft gesetzt werden könnte.

tster
quelle
4
Mit .Any können Sie Eigenschaften einfach vergleichen. Mit .Contains können Sie nur Objekte vergleichen und benötigen einen zusätzlichen IEqualityComparer, um Eigenschaften zu vergleichen.
Msfanboy
1
@msfanboy: Das stimmt, aber die Frage betraf speziell die Leistung und zeigte den Vergleich des gesamten Objekts. Ich denke also nicht, dass es hier relevant ist.
Tster
4

Ich nehme an, das würde von der Art abhängen, myCollectiondie vorschreibt, wie Contains()implementiert wird. Wenn zum Beispiel ein sortierter Binärbaum, könnte er intelligenter suchen. Es kann auch den Hash des Elements berücksichtigen. Any()Auf der anderen Seite wird die Sammlung aufgelistet, bis das erste Element gefunden ist, das die Bedingung erfüllt. Es gibt keine Optimierungen dafür, ob das Objekt eine intelligentere Suchmethode hatte.

Jeff Mercado
quelle
0

Contains () ist auch eine Erweiterungsmethode, die schnell funktionieren kann, wenn Sie sie richtig verwenden. Zum Beispiel:

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

Dies gibt die Abfrage

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

während Any () andererseits immer durch das O (n) iteriert.

Hoffe das wird funktionieren ....

Uwais
quelle