我最近开始大量使用LINQ,但没有看到任何有关任何LINQ方法的运行时复杂度的提及。显然,这里有许多因素,因此让我们将讨论限制在普通的IEnumerable
LINQ-to-Objects提供程序上。另外,让我们假设作为选择器/变异器/等的任何Func
都是廉价的O(1)操作。
很明显,所有单次遍历操作(Select
、Where
、Count
、Take / Skip
、Any / All
等)的时间复杂度将是O(n),因为它们只需要遍历一次序列; 虽然这也取决于惰性求值。
对于更复杂的操作,情况就不那么清楚了。类似集合的操作(Union
、Distinct
、Except
等)默认使用GetHashCode
(据我所知),因此可以合理地假设它们内部正在使用哈希表,总体而言,这些操作的时间复杂度也是O(n)。那么使用IEqualityComparer
的版本呢?
OrderBy
需要排序,因此最有可能是O(n log n)。如果它已经排序了呢?如果我说OrderBy().ThenBy()
并为两者提供相同的键,该怎么办?
我可以看到GroupBy
(和Join
)使用排序或哈希。是哪一个?
Contains
在List
上是O(n),但在HashSet
上是O(1)——LINQ会检查底层容器以查看是否可以加快速度吗?
真正的问题是——到目前为止,我一直信任操作的高性能。例如STL容器明确指定了每个操作的复杂度。在.NET库规范中是否有类似的LINQ性能保证?
更多问题(回复评论):
我没有考虑过开销,但我认为简单的Linq-to-Objects不会有太多开销。CodingHorror的帖子谈到了Linq-to-SQL,我可以理解解析查询并生成SQL会增加成本 - 对于对象提供程序是否存在类似的成本?如果存在,使用声明式语法和函数式语法是否不同?