问题描述
我只是偶然发现 IOrderedEnumerable.Contains [ ^ ],想知道这里是否有更多人遇到问题了?就是我...
考虑以下代码:
I just stumbled upon an oddity in IOrderedEnumerable.Contains[^] and was wondering if more people here had the problem or if it is just me...
Consider the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<int> list = new List<int>();
for (int i = 0; i < 1000000; i++)
{
list.Add(i);
}
IOrderedEnumerable<int> orderedList = list.OrderBy(i => i);
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 100; i++)
{ list.Contains(923456); }
sw.Stop();
Console.WriteLine("Calling contains on the List 100 times cost " + sw.Elapsed.ToString());
sw.Reset();
sw.Start();
for (int i = 0; i < 100; i++)
{ orderedList.Contains(923456); }
sw.Stop();
Console.WriteLine("Calling contains on the IOrderedEnumerable 100 times cost " + sw.Elapsed.ToString());
Console.ReadKey();
}
}
}
那里没错...我正在建立一个包含一百万个(唯一)整数的列表.即使已经排序,我仍在调用 OrderBy扩展方法 [ ^ ],我得到一个IOrderedEnumerable<int> [ ^ ].
现在,我将包含方法 [ ^ ]原始列表的100次,其值我知道会在后面的某个位置(假设列表< T> [ ^ ]将扫描每个元素,直到找到我要查找的元素为止,这几乎将占用最大数量时间来找到它).
之后,我在IOrderedEnumerable<T>
上执行相同的操作,但是我调用 IEnumerable< T>.包含扩展方法 [ ^ ].我希望这几乎与List<T>.Contains
相同,后者正在扫描集合中的每个项目,直到找到我要寻找的项目为止.
现在不应该困难.但是结果让我感到非常惊讶!List.Contains
大约花费了0,7至0,8秒进行了100次迭代... IOrderedEnumerable.Contains
花费了38秒!!!!
然后,我添加了这个小宝石:
Nothing wrong there... I am building a list with a million (unique) integers. Even though it is already sorted I am calling the OrderBy Extension Method[^] and I get an IOrderedEnumerable<int>[^].
Now I call the Contains Method[^] of the original list 100 times with a value of which I know will be somewhere at the back (assuming a List<T>[^] will scan every element until it finds the one I am looking for this will take almost the maximum amount of time to find it).
After that I do the same on the IOrderedEnumerable<T>
, but I call the IEnumerable<T>.Contains Extension Method[^]. I am expecting that this will pretty much do the same as List<T>.Contains
which is scanning every item in the collection until it finds the one I''m looking for.
Now that shouldn''t be to difficult. But I was pretty surprised by the result!List.Contains
took about 0,7 to 0,8 seconds for 100 iterations... IOrderedEnumerable.Contains
took a whooping 38 seconds!!!
I then added this little gem:
sw.Reset();
sw.Start();
for (int i = 0; i < 100; i++)
{ orderedList.ToList().Contains(923456); }
sw.Stop();
Console.WriteLine("Calling contains on the IOrderedEnumerable.ToList 100 times cost " + sw.Elapsed.ToString());
花了40秒!以某种方式将列表复制100次并调用Contains
仅比调用Contains
...花费2秒多的时间...
我还尝试将923456更改为1,以确保能够很快找到它,但实际上没有什么区别(尽管对于List<T>
确实如此).
我感到震惊,震惊,惊讶和无知...
我在这里想念什么吗?我曾期望两个集合大约需要花费相同的时间来进行计算...实际上,由于订购了IOrderedEnumerable<T>
,如果使用 [ ^ ]而不是 EqualComparer [ ^ ].
有任何想法吗?我没有了...
And it took 40 seconds! Somehow copying the list 100 times and calling Contains
only takes 2 seconds longer then only calling Contains
...
I also tried changing 923456 to 1 to make sure it was found rather quickly, but it actually made no difference (it did for the List<T>
though).
I am shocked, stunned, surprised and clueless...
Am I missing something here? I had expected both collections to take more or less the same time to compute... In fact, since an IOrderedEnumerable<T>
is ordered it could find values MUCH faster if it searched using a Comparer[^] rather than an EqualityComparer[^].
Any idea''s? I''m out of them...
推荐答案
orderedList.Contains(923456);
您会在每次迭代时再次使用该列表. ToList
强制将结果枚举在前面.
您可以通过将排序方式更改为
来查看
you''re resorting the list again for every iteration. ToList
forces the result to be enumerated up front.
You can see this by changing your sort to
IOrderedEnumerable<int> orderedList = list.OrderBy(i => { Console.WriteLine(" sorting=" + i); return i; });
(只需确保在一个非常小的列表上运行它即可:).
希望这会有所帮助,
弗雷德里克(Fredrik)
(just make sure to run that on a much, much smaller list :).
Hope this helps,
Fredrik
这篇关于关于IOrderedEnumerable的性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!