Biorąc pod uwagę ogromną kolekcję obiektów, czy istnieje różnica w wydajności między poniższymi?
myCollection.Contains(myElement)
myCollection.Any(currentElement => currentElement == myElement)
c#
linq
performance
benchmarking
SDReyes
źródło
źródło
Odpowiedzi:
Contains()
jest metodą instancji, a jej wydajność zależy w dużej mierze od samej kolekcji. Na przykładContains()
na aList
jest O (n), podczas gdyContains()
na aHashSet
jest O (1).Any()
jest metodą rozszerzającą i po prostu przejdzie przez kolekcję, stosując delegata do każdego obiektu. Dlatego ma złożoność O (n).Any()
jest jednak bardziej elastyczny, ponieważ możesz przekazać delegata.Contains()
może przyjąć tylko przedmiot.źródło
Contains
jest również metodą rozszerzającą przeciwkoIEnumerable<T>
(chociaż niektóre kolekcje mają również własneContains
metody instancji). Jak mówisz,Any
jest bardziej elastyczny niżContains
dlatego, że możesz przekazać mu niestandardowy predykat, aleContains
może być nieco szybszy, ponieważ nie musi wykonywać wywołania delegata dla każdego elementu.All()
działa podobnie.To zależy od kolekcji. Jeśli masz uporządkowaną kolekcję,
Contains
możesz przeprowadzić inteligentne wyszukiwanie (binarne, hash, b-tree itp.), Podczas gdy z `Any () w zasadzie utkniesz z wyliczaniem, dopóki go nie znajdziesz (zakładając LINQ-to-Objects) .Należy również zauważyć, że w przykładzie,
Any()
jest za pomocą==
operatora, który będzie sprawdzał referencyjnym równości, podczas gdyContains
użyjeIEquatable<T>
lubEquals()
metoda, która może być pominięte.źródło
Przypuszczam, że zależałoby to od typu,
myCollection
który dyktuje sposóbContains()
realizacji. Na przykład posortowane drzewo binarne może wyszukiwać mądrzej. Może również uwzględniać hash elementu.Any()
z drugiej strony wyliczy całą kolekcję, aż zostanie znaleziony pierwszy element spełniający warunek. Nie ma optymalizacji, jeśli obiekt miałby inteligentniejszą metodę wyszukiwania.źródło
Contains () jest również metodą rozszerzającą, która może działać szybko, jeśli używasz jej we właściwy sposób. Na przykład:
var result = context.Projects.Where(x => lstBizIds.Contains(x.businessId)).Select(x => x.projectId).ToList();
To da zapytanie
SELECT Id FROM Projects INNER JOIN (VALUES (1), (2), (3), (4), (5)) AS Data(Item) ON Projects.UserId = Data.Item
natomiast Any () z drugiej strony zawsze iteruje przez O (n).
Mam nadzieję, że to zadziała ....
źródło