LINQ Ring:大量集合的Any()vs Contains()


103

给定大量对象,以下各项之间是否存在性能差异?

集合包含

myCollection.Contains(myElement)

Enumerable.Any

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

7
10'000.000 int的集合。赢家是包含300%的物品。但值得考虑以下提到的差异。
SDReyes

1
这似乎显示出两者之间的鲜明对比:thedailywtf.com/Articles/State-of-the-UNION.aspx
David Peterson

Answers:


143

Contains()是实例方法,其性能在很大程度上取决于集合本身。例如,Contains()a List是O(n),而Contains()a HashSet是O(1)。

Any()是扩展方法,将简单地遍历集合,将委托应用于每个对象。因此,它的复杂度为O(n)。

Any()但是更灵活,因为您可以传递一个委托。Contains()只能接受一个对象。


27
Contains也是一种针对的扩展方法IEnumerable<T>(尽管某些集合也有自己的Contains实例方法)。如您所说,Any它比Contains您可以传递给它一个自定义谓词更灵活,但由于它不需要为每个元素执行委托调用,因此它Contains 可能稍快一些。
路加福音2010年

1
是否任何()在集合中的所有对象进行操作或它与第一场比赛结束?
Quarkly

1
至少根据消息来源,它会在第一个比赛时停止。All()操作类似。
Etienne de Martel,

13

这取决于收藏。如果您有一个有序的集合,则Contains可能会进行智能搜索(二进制,哈希,b树等),而使用`Any()则基本上是坚持枚举,直到找到它为止(假定LINQ-to-Objects) 。

还要注意,在您的示例中,Any()正在使用==运算符,该运算符将检查引用相等性,而Contains将使用IEquatable<T>Equals()方法,该运算符可能会被覆盖。


4
使用.Any,您可以轻松比较属性。使用.Contains,您可以只比较对象,并且需要一个额外的IEqualityComparer来比较属性。
msfanboy 2011年

1
@msfanboy:是的,但是问题是关于性能的,并显示了对整个对象的比较。因此,我认为这里并不重要。
tster

4

我想这取决于myCollection决定如何Contains()实现的is 的类型。例如,如果使用排序的二叉树,则搜索会更智能。同样,它也可以考虑元素的哈希值。 Any()另一方面,将枚举整个集合,直到找到满足条件的第一个元素。如果对象具有更智能的搜索方法,则没有优化。


0

Contains()也是一种扩展方法,如果以正确的方式使用它,它可以快速工作。例如:

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

这将给查询

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

另一方面,Any()总是迭代O(n)。

希望这会工作....

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.