在Find,Single,First中,哪一个最快?

时间:2011-01-27 07:54:54

标签: c#

我想最小化从列表中检索单个唯一元素所需的时间。 哪一个是FindSingleFirst中最快的方法? 请注意,搜索键是唯一的ID。

5 个答案:

答案 0 :(得分:30)

最快(对于大型集合)是将它们与Dictionary<TKey,TValue>键入并使用它。

SingleFirst做不同的事情; Single总是迭代整个集合,即使它在列表的开头找到它,因此First通常比Single更快,因为它会短路。

答案 1 :(得分:26)

First将比Single更快,因为它可以在找到匹配后立即终止。另一方面,这意味着它验证只有一个项与谓词匹配。

Find应该与First一样快,但不太便于携带,因为它只适用于列表。如果您一般使用LINQ,我会尝试坚持使用LINQ运算符,除非使用替代方案有明显的好处。

正如马克所说,如果你要经常这样做,你应该使用Dictionary<,>。您可以使用ToDictionary运算符轻松完成此操作:

var dictionary = list.ToDictionary(x => x.Id);
// Now you can look up by ID really quickly

显然创建字典需要一些时间才能开始,所以如果 多次搜索,你只想这样做。

答案 2 :(得分:2)

它们是不同的方法。 Find中定义了List<T>,它与FirstEnumerable.cs中定义的IEnumerable<T>几乎相同,是Single上的扩展方法。如果找到一个条件项目(不需要遍历整个集合),它们都将返回,因此它们有轻微的性能差异。

虽然Single返回条件项,但也保证此项是唯一符合条件的项。因此,在大多数情况下,FirstFind / {{1}}慢,因为它需要遍历集合。

答案 3 :(得分:1)

作为现有答案的补充:List.Find比IEnumerable.First快得多,因为第一个可以在List的内部数组上运行。后者必须通过IList接口。

答案 4 :(得分:0)

单次检查整个列表以确保确实只有一个,因此它将始终命中列表中的每个项目。

查找到第一项后,查找和第一将停止。查找实际上更接近FirstOrDefault,因为如果找不到匹配项,查找将返回默认值。首先会引发异常。

单个: https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/Single.cs

using (IEnumerator<TSource> e = source.GetEnumerator())
        {
            while (e.MoveNext())
            {
                TSource result = e.Current;
                if (predicate(result))
                {
                    while (e.MoveNext())
                    {
                        if (predicate(e.Current))
                        {
                            ThrowHelper.ThrowMoreThanOneMatchException();
                        }
                    }

                    return result;
                }
            }
        }

第一名:https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/First.cs

经过一番逻辑,可以归结为:

foreach (TSource element in source)
        {
            if (predicate(element))
            {
                found = true;
                return element;
            }
        }

查找: https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs

for(int i = 0 ; i < _size; i++) {
            if(match(_items[i])) {
                return _items[i];
            }
        }