2010-12-14 11 views
74

Biorąc pod uwagę ogromną kolekcję obiektów, czy występuje różnica wydajności między następującymi elementami?Pierścień LINQ: Any() kontra Contains() dla ogromnych kolekcji

Collection.Contains:

myCollection.Contains(myElement) 

Enumerable.Any:

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

Zbiór 10 000 000 int. Zwycięzca to zawiera 300%. ale warto wziąć pod uwagę wymienione poniżej wariancje. – SDReyes

+1

Wydaje się to wykazywać wyraźny kontrast między tymi dwoma: http://thedailywtf.com/Articles/State-of-the-UNION.aspx –

Odpowiedz

98

Contains() jest metodą instancji, a jej wydajność zależy w dużej mierze od samej kolekcji. Na przykład, Contains() na liście to O (n), a Contains() na HashSet to O (1).

Dowolna() jest metodą rozszerzenia i po prostu przechodzi przez kolekcję, stosując delegata na każdym obiekcie. Ma więc złożoność O (n).

Dowolny() jest jednak bardziej elastyczny, ponieważ można przekazać delegata. Contains() może akceptować tylko obiekt.

+20

'Contains' jest również metodą rozszerzenia względem' IEnumerable '(chociaż niektóre kolekcje mają również własną metodę instancji' Contains'). Jak już mówisz, 'Any' jest bardziej elastyczny niż' Contains', ponieważ możesz przekazać mu niestandardowy predykat, ale 'Contains' * może * być nieco szybszy, ponieważ nie musi wykonywać delegacji dla każdego elementu. – LukeH

8

To zależy od kolekcji. Jeśli masz uporządkowaną kolekcję, Contains może wykonać inteligentne wyszukiwanie (binarne, hash, b-drzewo, itp.), Podczas gdy z Any() jesteś w zasadzie zatrzymany z wyliczaniem, dopóki go nie znajdziesz (zakładając LINQ do Objects)

Zauważ, że w twoim przykładzie Any() używa operatora "==", który sprawdzi równość referencyjną, podczas gdy Contains użyje metody IEquitable lub Equals(), która może zostać przesłonięta.

+1

Z. Any możesz łatwo porównać właściwości. Z .Contains możesz po prostu porównać obiekty i potrzebujesz dodatkowego IEqualityComparer, aby porównać właściwości. – msfanboy

+1

@msfanboy: To prawda, ale pytanie dotyczyło konkretnie wydajności i pokazało porównanie całego obiektu. Nie sądzę, że ma to znaczenie tutaj. – tster

4

Przypuszczam, że to zależy od typu myCollection, który określa, w jaki sposób implementowane jest Contains(). Jeśli posortowane drzewo binarne na przykład może wyszukiwać inteligentniej. Może również brać pod uwagę hasz elementu. Any() z drugiej strony będzie wyliczać przez kolekcję do momentu znalezienia pierwszego elementu, który spełnia warunek. Nie ma optymalizacji, jeśli obiekt miał inteligentniejszą metodę wyszukiwania.