我想最小化从列表中检索单个唯一元素所需的时间。
哪一个是Find
,Single
和First
中最快的方法?
请注意,搜索键是唯一的ID。
答案 0 :(得分:30)
最快(对于大型集合)是将它们与Dictionary<TKey,TValue>
键入并使用它。
Single
和First
做不同的事情; 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>
,它与First
中Enumerable.cs
中定义的IEnumerable<T>
几乎相同,是Single
上的扩展方法。如果找到一个条件项目(不需要遍历整个集合),它们都将返回,因此它们有轻微的性能差异。
虽然Single
返回条件项,但也保证此项是唯一符合条件的项。因此,在大多数情况下,First
比Find
/ {{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];
}
}