Dada uma enorme coleção de objetos, há uma diferença de desempenho entre os itens a seguir?
myCollection.Contains(myElement)
myCollection.Any(currentElement => currentElement == myElement)
Dada uma enorme coleção de objetos, há uma diferença de desempenho entre os itens a seguir?
myCollection.Contains(myElement)
myCollection.Any(currentElement => currentElement == myElement)
Respostas:
Contains()
é um método de instância e seu desempenho depende muito da própria coleção. Por exemplo, Contains()
em a List
é O (n), enquanto Contains()
em a HashSet
é O (1).
Any()
é um método de extensão e simplesmente percorrerá a coleção, aplicando o delegado em cada objeto. Portanto, tem uma complexidade de O (n).
Any()
é mais flexível, pois você pode passar um delegado. Contains()
só pode aceitar um objeto.
Contains
também é um método de extensão contra IEnumerable<T>
(embora algumas coleções também tenham seu próprio Contains
método de instância). Como você disse, Any
é mais flexível do que Contains
porque você pode passar um predicado personalizado, mas Contains
pode ser um pouco mais rápido porque não precisa executar uma invocação de delegado para cada elemento.
All()
opera de forma semelhante.
Depende da coleção. Se você tem uma coleção ordenada, então Contains
pode fazer uma pesquisa inteligente (binária, hash, árvore b, etc.), enquanto com `Any () você basicamente fica preso na enumeração até encontrá-la (assumindo LINQ-to-Objects) .
Observe também que em seu exemplo, Any()
está usando o ==
operador que verificará a igualdade referencial, enquanto Contains
usará IEquatable<T>
ou o Equals()
método, que pode ser substituído.
Suponho que isso dependeria do tipo de myCollection
é que dita como Contains()
é implementado. Se uma árvore binária classificada, por exemplo, ela poderia pesquisar de forma mais inteligente. Também pode levar em consideração o hash do elemento. Any()
por outro lado, irá enumerar através da coleção até que o primeiro elemento que satisfaça a condição seja encontrado. Não há otimizações para se o objeto tivesse um método de pesquisa mais inteligente.
Contains () também é um método de extensão que pode funcionar rapidamente se você usá-lo da maneira correta. Por ex:
var result = context.Projects.Where(x => lstBizIds.Contains(x.businessId)).Select(x => x.projectId).ToList();
Isso dará a consulta
SELECT Id
FROM Projects
INNER JOIN (VALUES (1), (2), (3), (4), (5)) AS Data(Item) ON Projects.UserId = Data.Item
enquanto Any (), por outro lado, sempre itera através do O (n).
Espero que isso funcione ....