【问题标题】:I need to iterate and count. What is fastest or preferred: ToArray() or ToList()? [duplicate]我需要迭代和计数。什么是最快或首选:ToArray() 或 ToList()? [复制]
【发布时间】:2010-12-22 01:12:44
【问题描述】:

可能重复:
Is it better to call ToList() or ToArray() in LINQ queries?

我有这样的代码:

void Foobar(string[] arr, Dictionary<string, string[]>)
{
   var t = arr.Intersect(dic.Keys).ToList(); // .or ToArray() ?
   foreach(var item in t)
   {
      ..
   }

   var j = t.Count; // also I need this
}

首选哪种方法?

我可以不带任何东西,但我需要知道大小,我不想打电话给Enumerable.Count&lt;T&gt;() - 似乎比Array&lt;T&gt;.SizeList&lt;T&gt;.Count 做更多的动作。我说的对吗?

【问题讨论】:

标签: c# performance arrays list ienumerable


【解决方案1】:

实际上,在 Count(IEnumerable) 的当前 MS 实现中,有一个快捷方式可以查看 IEnumerable 是否为 ICollection 并在其上调用 Count。所以计算元素的性能应该是可比的。

ToList 和 ToArray 有点相同。如果 IEnumerable 是 ICollection,则改为调用 CopyTo 方法,这样会快一些。

因此,请选择使您的代码最易读的因素,并为您的用例进行基准测试以获得明确的答案。

更新: 我做了一个简单的基准测试。

从数组开始:var items = Enumerable.Range(1,1000).ToArray();

  • 调用 ToList() : 25ms / 10000
  • 调用 ToArray() : 23 ms / 10000

以 IEnumerable 开头:var items = Enumerable.Range(1,1000);

  • 调用 ToList() : 168ms / 10000
  • 调用 ToArray() : 171 ms / 10000

所以基本上你会得到相当的性能。

【讨论】:

    【解决方案2】:

    如果您真的关心性能,您应该遍历IEnumerable 并随时计算它。这避免了必须完全创建一个新集合,并且交集只需迭代一次:

    void Foobar(string[] arr, Dictionary<string, string[]>)
    {
       var t = arr.Intersect(dic.Keys);
       int count = 0;
       foreach(var item in t)
       {
          count++;
          ..
       }
    
       var j = count;
    }
    

    但就像其他人所说:这有微优化的味道。如果在这种情况下性能真的很重要,至少要进行性能分析以找出哪种方法对您来说确实是最快的。

    【讨论】:

    • 但是如果您非常关心性能,那么这意味着您必须为具有 X 个项目的 IEnumerable 更新计数器变量 X 次 - 与查找 Count 相比,这可能更有效大收藏。
    • @Yaakov:必须计算集合的大小。通过计算自己,您只需遍历集合一次。如果将集合转换为列表数组,则集合必须至少交互两次(一次用于转换,一次用于foreach 循环。
    • 根据反射器,List、ArrayList 和 Array 各自在执行直接计数时引用的对象内保存一个长度或大小变量 - 因此在 Array 或 List 上运行 Count 不会引起另一个枚举。
    • @Yaakov:不,关键是从枚举创建数组或列表会导致创建迭代。然后,您必须遍历对创建的数组或列表进行的任何处理。相反,只需枚举收集计数和处理过程即可。
    • @jason 为了避免在我不需要一次全部创建列表/数组时重新枚举枚举并且我需要它们在同一个枚举的不同位置,你有什么建议?跨度>
    【解决方案3】:

    差异可能很小,值得使用更适合您需求的方法。微优化的味道。

    在这种情况下,既然您所做的只是枚举集合并计算集合(这两者都可以使用 IEnumerable 完成),为什么不将其保留为 IEnumerable?

    【讨论】:

    • 我想这自然会引出另一个问题:由于大多数意图和目的的性能是相同的,我应该使用哪种类型作为我的“默认”集合类型?我个人更喜欢List&lt;T&gt;,因为它的长度不是只读的,但过去我很难说服其他人它比T[] 提供了更好的“默认”集合类型选择。
    • @romkyns:绝对是,这是一个通用的默认类。我更喜欢将数组作为固定长度的集合。我只在明确需要时才使用动态长度
    • 为了避免在我不需要一次全部并且需要它们在同一个可枚举的不同位置时重新枚举用于创建列表/数组的枚举,您有什么建议?
    猜你喜欢
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多