C# Linq Count() 比 List.Count 或 Array.Length 快还是慢?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/981254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is the Linq Count() faster or slower than List.Count or Array.Length?
提问by NotDan
Is the LINQ Count()
method any faster or slower than List<>.Count
or Array.Length
?
LINQCount()
方法是否比List<>.Count
或更快或更慢Array.Length
?
采纳答案by JaredPar
In general Slower. LINQ's Count in general is an O(N)
operation while List.Count
and Array.Length
are both guaranteed to be O(1)
.
一般比较慢。LINQ 的 Count 通常是一个O(N)
操作 whileList.Count
并且Array.Length
都保证是O(1)
.
However it some cases LINQ will special case the IEnumerable<T>
parameter by casting to certain interface types such as IList<T>
or ICollection<T>
. It will then use that Count method to do an actual Count()
operation. So it will go back down to O(1)
. But you still pay the minor overhead of the cast and interface call.
但是,在某些情况下,LINQ 会IEnumerable<T>
通过将参数强制转换为某些接口类型(例如IList<T>
或 )来对参数进行特殊处理ICollection<T>
。然后它将使用该 Count 方法进行实际Count()
操作。所以它会回到O(1)
. 但是您仍然需要支付转换和接口调用的少量开销。
回答by Jake Pearson
I believe that if you call Linq.Count() on either an ICollection or IList (like an ArrayList or List) then it will just return the Count property's value. So the performance will be about the same on plain collections.
我相信,如果您在 ICollection 或 IList(如 ArrayList 或 List)上调用 Linq.Count() 那么它只会返回 Count 属性的值。因此,在普通集合上的性能将大致相同。
回答by Marc Gravell
The Enumerable.Count()
method checks for ICollection<T>
, using .Count
- so in the case of arrays and lists, it is not much more inefficient (just an extra level of indirection).
该Enumerable.Count()
方法检查ICollection<T>
, using .Count
- 所以在数组和列表的情况下,它的效率并不低(只是额外的间接级别)。
回答by Jose
I would say it depends on the List. If it is an IQueryable that is a table in a db somewhere then Count() will be much fasterbecause it doesn't have to load all of the objects. But if the list is in-memory i would guess that the Count property would be faster if not about the same.
我会说这取决于列表。如果它是一个 IQueryable 是某个数据库中的表,那么 Count() 会快得多,因为它不必加载所有对象。但是如果列表在内存中,我猜 Count 属性会更快,如果不一样的话。
回答by Sam Saffron
Marc has the right answer but the devil is in the detail.
马克有正确的答案,但问题在于细节。
On my machine:
在我的机器上:
- For arrays .Length is about 100 times faster than .Count()
- For Lists .Count is about 10 times faster than .Count() - Note: I would expect similar performance from all Collections that implement
IList<T>
- 对于数组 .Length 比 .Count() 快大约 100 倍
- 对于列表 .Count 比 .Count() 快大约 10 倍 - 注意:我希望所有实现的集合都有相似的性能
IList<T>
Arrays start off slower since .Length involves only a single operation, .Count on arrays involves a layer of indirection. So .Count on arrays starts off 10x slower (on my machine), which could be one of those reasons the interface is implemented explicitly. Imagine if you had an object with two public properties, .Count and .Length. Both do the exact same thing but .Count is 10X slower.
数组开始较慢,因为 .Length 只涉及单个操作,数组上的 .Count 涉及一个间接层。因此,数组上的 .Count 开始时慢 10 倍(在我的机器上),这可能是显式实现接口的原因之一。想象一下,如果您有一个具有两个公共属性的对象,.Count 和 .Length。两者都做完全相同的事情,但 .Count 慢 10 倍。
Of course non of this really makes much of a difference since you would have to be counting your arrays and lists millions of times a second to feel a performance hit.
当然,这些都没有真正产生很大的不同,因为您必须计算数组并每秒列出数百万次才能感受到性能下降。
Code:
代码:
static void TimeAction(string description, int times, Action func) {
var watch = new Stopwatch();
watch.Start();
for (int i = 0; i < times; i++) {
func();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}
static void Main(string[] args) {
var array = Enumerable.Range(0, 10000000).ToArray();
var list = Enumerable.Range(0, 10000000).ToArray().ToList();
// jit
TimeAction("Ignore and jit", 1 ,() =>
{
var junk = array.Length;
var junk2 = list.Count;
array.Count();
list.Count();
});
TimeAction("Array Length", 1000000, () => {
var tmp1 = array.Length;
});
TimeAction("Array Count()", 1000000, () =>
{
var tmp2 = array.Count();
});
TimeAction("Array Length through cast", 1000000, () =>
{
var tmp3 = (array as ICollection<int>).Count;
});
TimeAction("List Count", 1000000, () =>
{
var tmp1 = list.Count;
});
TimeAction("List Count()", 1000000, () =>
{
var tmp2 = list.Count();
});
Console.ReadKey();
}
Results:
结果:
Array Length Time Elapsed 3 ms Array Count() Time Elapsed 264 ms Array Length through cast Time Elapsed 16 ms List Count Time Elapsed 3 ms List Count() Time Elapsed 18 ms
回答by Adam Tuliper - MSFT
Some additional info - LINQ Count - the difference between using it and not can be huge - and this doesn't have to be over 'large' collections either. I have a collection formed from linq to objects with about 6500 items (big.. but not huge by any means) . Count() in my case takes several seconds. Converting to a list (or array, whatver) the count is then virtually immediate. Having this count in an inner loop means the impact could be huge. Count enumerates through everything. An array and a list are both 'self aware' of their lengths and do not need to enumerate them. Any debug statements (log4net for ex) that reference this count() will also then slow everything down considerably more. Do yourself a favor and if you need to reference this often save the count size and only call it once on a LINQ collection unless you convert it to a list and then can reference away without a performance hit.
一些附加信息 - LINQ Count - 使用它和不使用它之间的区别可能很大 - 这也不必超过“大”集合。我有一个从 linq 到对象的集合,大约有 6500 个项目(大.. 但无论如何都不大)。Count() 在我的情况下需要几秒钟。转换为列表(或数组,无论什么),计数实际上是立即的。在内部循环中进行计数意味着影响可能是巨大的。计数通过一切枚举。数组和列表都知道它们的长度,不需要枚举它们。任何引用此 count() 的调试语句(例如 log4net)也将大大减慢一切。
Here is a quick test of what I was talking about above. Note every time we call Count() our collection size changes.. hence evaluation happens, which is more than an expected 'count' operation. Just something to be aware of : )
这是对我上面所说的内容的快速测试。请注意,每次我们调用 Count() 时,我们的集合大小都会发生变化……因此会发生评估,这不仅仅是预期的“计数”操作。只是需要注意的事情:)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LinqTest
{
class TestClass
{
public TestClass()
{
CreateDate = DateTime.Now;
}
public DateTime CreateDate;
}
class Program
{
static void Main(string[] args)
{
//Populate the test class
List list = new List(1000);
for (int i=0; i<1000; i++)
{
System.Threading.Thread.Sleep(20);
list.Add(new TestClass());
if(i%100==0)
{
Console.WriteLine(i.ToString() + " items added");
}
}
//now query for items
var newList = list.Where(o=> o.CreateDate.AddSeconds(5)> DateTime.Now);
while (newList.Count() > 0)
{
//Note - are actual count keeps decreasing.. showing our 'execute' is running every time we call count.
Console.WriteLine(newList.Count());
System.Threading.Thread.Sleep(500);
}
}
}
}
回答by Sajithd
List.Count
or Array.Length
is indeed faster than Linq Count()
. Because Linq Count()
will iterate through the whole list of items to count. List.Count
or Array.Length
use their property.
List.Count
或者Array.Length
确实比 Linq 快Count()
。因为 LinqCount()
将遍历要计数的整个项目列表。List.Count
或Array.Length
使用他们的财产。