LINQ.First()和Array[0]之间的区别

10

我想知道 list.first() 和 list[0] 在底层发生了什么,以及哪一个更有效率。

例如哪一个更快?

for(int i = 0; i < 999999999999... i++)
{
    str.Split(';').First() vs. str.Split(';')[0]

    list.Where(x => x > 1).First() vs. list.Where(x => x > 1).ToList()[0]
}

如果有重复的问题,我很抱歉。


4
哪种更快? - Soner Gönül
list.Where(x => x > 1).First()list.Where(x => x > 1).ToList()[0],第一个解决方案具有更好的性能 - 第二个解决方案将枚举整个序列,而第一个解决方案将在第一个元素处停止。 - user2160375
4
@Marwie - 这不是完全重复,因为它并没有回答第一个比较。 - Sayse
3
@Marwie - 由于您添加了转换操作,这将产生很大的影响。 - Sayse
对于第二个比较行,请参考 https://dev59.com/gm025IYBdhLWcg3wVkif - Marwie
显示剩余6条评论
4个回答

10

哪个更好?数组访问器,因为它不需要在堆栈上放置方法并且无需执行First方法最终才能到达数组访问器。

正如Enumerable的参考源代码所示,First()实际上是:

IList<TSource> list = source as IList<TSource>;
if (list != null) {
    if (list.Count > 0) return list[0];
}

所以它不会执行其他任何操作,只是需要更多的步骤来到达目标。

对于您的第二个部分 (list.Where(x => x > 1).First() vs. list.Where(x => x > 1).ToList()[0]):

Where 返回一个 IEnumerable,它不是 IList,因此它不会执行 First 方法的第一部分,而是执行第二部分:

using (IEnumerator<TSource> e = source.GetEnumerator()) {
    if (e.MoveNext()) return e.Current;
}

这将逐一遍历每个项目,直到找到所需的索引。在这种情况下是0,因此它会很快到达。另一个调用ToList的方法始终不太高效,因为它必须创建一个新对象并将所有项目按顺序放入其中以获取第一个项目。第一个调用肯定更快。


@PatrickHofman .First.ToList()[0] - Renatas M.
@Rawling 请查看我的评论或打开Marwie链接。 - user2160375
@Rawling 好的,我的错。 - user2160375

7

简单的性能压缩 http://pastebin.com/bScgyDaM

str.Split(';').First(); :                        529103
str.Split(';')[0]; :                             246753
list.Where(x => x == "a").First(); :              98590
list.Where(x => x == "a").ToList()[0]; :         230858

First vs [0] 如果您有简单的数组,那么 [0] 会更快,因为它只在内存中计算加法。但是,如果与其他LINQ命令组合使用,则 First() 更快。例如 Where().First() 会一直搜索直到找到第一个元素, 而 Where().ToList()[0] 则会查找所有元素,然后将其转换为列表并执行简单的计算。

另一个要注意的是,Where() 是一个延迟方法。只有包含延迟方法的查询在枚举结果项之前不会执行。所以您可以...

list.Where( x => x>12);
list.add(10);
list.add(13);
foreach (int item in list)
{
   Console.WriteLine(item); 
}

13会被附加到结果中,但10不会,因为10和13是后来添加到列表中的,而此时列表已经被搜索。

如果您想了解更多关于Linq的内容,可以阅读Joseph Rattz和Adam Freeman撰写的Pro LINQ一书http://www.apress.com/9781430226536


1
这些之间没有显著的区别,你将得到几乎相同的结果:
 str.Split(';').First() vs. str.Split(';')[0]

对于您的第二个比较,这里您只询问了第一个元素。
list.Where(x => x > 1).First()

所以一旦WhereIterator返回一个项目,它就完成了。但是在第二个例子中,您将所有结果放入列表中,然后使用索引器获取第一个项目,因此会更慢。

1
  • list.Where(x => x > 1).First()list.Where(x => x > 1).ToList()[0]

    应用于Enumerable时,First()应该更快,因为它具有延迟执行。在您的情况下,只要找到符合条件Where(x => x > 1)的列表中的一个项目,结果就会被返回。

    在第二个示例中,必须完全枚举初始列表,将符合条件的所有项放入临时列表中,然后使用数组访问器获取第一项。

  • str.Split(';').First()str.Split(';')[0]

    在这种情况下,方法Split()已经返回一个数组。数组访问器可能会稍微快一点,但在大多数情况下,性能提升将是微不足道的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接