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)
c#
linq
performance
benchmarking
SDReyes
fonte
fonte
Respostas:
Contains()
é um método de instância e seu desempenho depende muito da própria coleção. Por exemplo,Contains()
em aList
é O (n), enquantoContains()
em aHashSet
é 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.fonte
Contains
também é um método de extensão contraIEnumerable<T>
(embora algumas coleções também tenham seu próprioContains
método de instância). Como você disse,Any
é mais flexível do queContains
porque você pode passar um predicado personalizado, masContains
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, enquantoContains
usaráIEquatable<T>
ou oEquals()
método, que pode ser substituído.fonte
Suponho que isso dependeria do tipo de
myCollection
é que dita comoContains()
é 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.fonte
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 ....
fonte