我正在使用代码库,其中需要经常搜索列表以查找单个元素。
使用Predicate和Find()比在列表上手动执行枚举更快吗?
例如:
string needle = "example";
FooObj result = _list.Find(delegate(FooObj foo) {
return foo.Name == needle;
});
VS
string needle = "example";
foreach (FooObj foo in _list)
{
if (foo.Name == needle)
return foo;
}
虽然它们在功能上是等同的,但它们在性能方面是否相同?
答案 0 :(得分:5)
它们在性能上并不相同。 Find()方法需要为列表中的每个项调用一个方法(在本例中为委托)。与内联比较相比,方法调用不是免费的并且相对昂贵。 foreach版本不需要为每个对象调用额外的方法。
话虽如此,在实际分析我的代码并发现这是一个问题之前,我不会根据性能选择其中一个。我还没有发现这个场景的开销对于我编写的代码来说都是一个“热门路径”问题,而且我在Find和其他类似方法中使用了这个模式。
答案 1 :(得分:4)
如果您的列表搜索速度太慢,您可能比线性搜索做得更好。如果您可以对列表进行排序,则可以使用二进制搜索在O(lg n)时间内查找元素。
如果您正在搜索整个批次,请考虑使用词典替换该列表,以按名称索引对象。
答案 2 :(得分:3)
从技术上讲,委托版本的运行时性能会比其他版本略差 - 但在大多数情况下,你很难察觉到任何差异。
更重要的是(IHMO)代码时间表现能够写出你想要的东西,而不是你想要的东西。这在可维护性方面有很大的不同。
这个原始代码:
string needle = "example";
foreach (FooObj foo in _list)
{
if (foo.Name == needle)
return foo;
}
要求任何维护者阅读代码并了解您正在寻找特定项目。
此代码
string needle = "example";
return _list.Find(
delegate(FooObj foo)
{
return foo.Name == needle;
});
明确表示您正在寻找特定项目 - 更快理解。
最后,这段代码使用了C#3.0中的功能:
string needle = "example";
return _list.Find( foo => foo.Name == needle);
做了完全相同的事情,但在一行中,阅读和理解的速度更快(好吧,一旦你理解lambda expressions,无论如何)。
总之,鉴于替代方案的性能几乎相同,请选择使代码更易于阅读和维护的方法。
答案 3 :(得分:2)
“我正在使用代码库,其中列表需要经常搜索以获取单个元素”
最好将数据结构更改为Dictionary而不是List以获得更好的性能
答案 4 :(得分:1)
类似的问题被问到List.ForEach与foreach-iteration(foreach vs someList.Foreach(){})。
在这种情况下,List.ForEach有点快。
答案 5 :(得分:0)
正如贾里德指出的,存在分歧。
但是,一如既往,除非你知道这是一个瓶颈,否则不要担心。如果它是一个瓶颈,那可能是因为列表很大,在这种情况下你应该考虑使用更快的查找 - 哈希表或二叉树,或者甚至只是对列表进行排序并进行二进制搜索会给你log(n)性能将比调整线性情况产生更大的影响。