FindAll 与 Where 扩展方法 [英] FindAll vs Where extension-method

查看:18
本文介绍了FindAll 与 Where 扩展方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只想知道FindAll"是否会比Where"扩展方法更快,为什么?

I just want know if a "FindAll" will be faster than a "Where" extentionMethod and why?

示例:

myList.FindAll(item=> item.category == 5);

myList.Where(item=> item.category == 5);

哪个更好?

推荐答案

好吧,FindAll 将匹配的元素复制到一个新列表中,而 Where 只是返回一个懒惰的计算结果序列 - 不需要复制.

Well, FindAll copies the matching elements to a new list, whereas Where just returns a lazily evaluated sequence - no copying is required.

因此我希望 WhereFindAll 稍微快一点,即使结果序列被完全评估 - 当然还有 Where 的惰性评估策略 意味着如果您只查看(例如)第一个匹配项,则不需要检查列表的其余部分.(正如 Matthew 指出的那样,需要维护 Where 的状态机.但是,这只会有固定的内存成本 - 而构建新列表可能需要多个数组分配等.)

I'd therefore expect Where to be slightly faster than FindAll even when the resulting sequence is fully evaluated - and of course the lazy evaluation strategy of Where means that if you only look at (say) the first match, it won't need to check the remainder of the list. (As Matthew points out, there's work in maintaining the state machine for Where. However, this will only have a fixed memory cost - whereas constructing a new list may require multiple array allocations etc.)

基本上,FindAll(predicate) 更接近于 Where(predicate).ToList() 而不是 Where(predicate).

Basically, FindAll(predicate) is closer to Where(predicate).ToList() than to just Where(predicate).

只是为了对 Matthew 的回答做出更多反应,我认为他的测试还不够彻底.他的谓词恰好选择了一半的项目.这是一个简短但完整的程序,它测试相同的列表,但具有三个不同的谓词 - 一个不选择项目,一个选择所有项目,一个选择一半.在每种情况下,我都运行了 50 次测试以获得更长的时间.

Just to react a bit more to Matthew's answer, I don't think he's tested it quite thoroughly enough. His predicate happens to pick half the items. Here's a short but complete program which tests the same list but with three different predicates - one picks no items, one picks all the items, and one picks half of them. In each case I run the test fifty times to get longer timing.

我正在使用 Count() 来确保对 Where 结果进行完全评估.结果显示,收集到一半左右的结果,两者并驾齐驱.没有收集结果,FindAll 获胜.收集所有结果,Where获胜.我觉得这很有趣:随着找到越来越多的匹配项,所有解决方案都变得更慢:FindAll 需要进行更多的复制,而 Where 必须返回匹配的值而不是只是在 MoveNext() 实现中循环.但是,FindAll 的速度比 Where 慢,因此失去了早期的领先优势.很有趣.

I'm using Count() to make sure that the Where result is fully evaluated. The results show that collecting around half the results, the two are neck and neck. Collecting no results, FindAll wins. Collecting all the results, Where wins. I find this intriguing: all of the solutions become slower as more and more matches are found: FindAll has more copying to do, and Where has to return the matched values instead of just looping within the MoveNext() implementation. However, FindAll gets slower faster than Where does, so loses its early lead. Very interesting.

结果:

FindAll: All: 11994
Where: All: 8176
FindAll: Half: 6887
Where: Half: 6844
FindAll: None: 3253
Where: None: 4891

(使用/o+/debug- 编译并从命令行运行,.NET 3.5.)

(Compiled with /o+ /debug- and run from the command line, .NET 3.5.)

代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

class Test
{
    static List<int> ints = Enumerable.Range(0, 10000000).ToList();

    static void Main(string[] args)
    {
        Benchmark("All", i => i >= 0); // Match all
        Benchmark("Half", i => i % 2 == 0); // Match half
        Benchmark("None", i => i < 0); // Match none
    }

    static void Benchmark(string name, Predicate<int> predicate)
    {
        // We could just use new Func<int, bool>(predicate) but that
        // would create one delegate wrapping another.
        Func<int, bool> func = (Func<int, bool>) 
            Delegate.CreateDelegate(typeof(Func<int, bool>), predicate.Target,
                                    predicate.Method);
        Benchmark("FindAll: " + name, () => ints.FindAll(predicate));
        Benchmark("Where: " + name, () => ints.Where(func).Count());
    }

    static void Benchmark(string name, Action action)
    {
        GC.Collect();
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 50; i++)
        {
            action();
        }
        sw.Stop();
        Console.WriteLine("{0}: {1}", name, sw.ElapsedMilliseconds);
    }
}

这篇关于FindAll 与 Where 扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆