我正在使用代码库,其中需要经常搜索列表以查找单个元素。

使用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;
}

虽然它们在功能上是等同的,但它们在性能方面是否相同?

有帮助吗?

解决方案

它们在性能上并不相同。 Find()方法需要为列表中的每个项调用一个方法(在本例中为委托)。与内联比较相比,方法调用不是免费的并且相对昂贵。 foreach版本不需要为每个对象调用额外的方法。

话虽如此,在实际分析我的代码并发现这是一个问题之前,我不会根据性能选择其中一个。我还没有发现这个场景的开销是每个都是“热门路径”的。代码我写的问题,我使用Find和其他类似的方法很多地使用这个模式。

其他提示

如果您的列表搜索速度太慢,您可能比线性搜索做得更好。如果您可以对列表进行排序,则可以使用二进制搜索在O(lg n)时间内查找元素。

如果您正在搜索整个批次,请考虑使用词典替换该列表,以按名称索引对象。

从技术上讲,委托版本的运行时性能会比其他版本略差 - 但在大多数情况下,您很难察觉到任何差异。

更重要的是(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表达式,无论如何)。

总之,鉴于替代方案的性能几乎相同,请选择使代码更易于阅读和维护的方法。

“我正在使用代码库,其中列表需要经常搜索以获取单个元素”

最好将数据结构更改为Dictionary而不是List以获得更好的性能

类似的问题被问到List.ForEach与foreach-iteration( foreach vs someList.Foreach() {} )。

在这种情况下,List.ForEach有点快。

正如贾里德指出的,存在分歧。

但是,一如既往,除非你知道这是一个瓶颈,否则不要担心。如果它是一个瓶颈,那可能是因为列表很大,在这种情况下你应该考虑使用更快的查找 - 哈希表或二叉树,或者甚至只是对列表进行排序并进行二进制搜索会给你log(n)性能将比调整线性情况产生更大的影响。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top