20.List初始化效率比较

  1. 20.List初始化效率比较
    1. 20.1 题目
    2. 20.2 深入解析
      1. 详细解释
      2. 总结
    3. 20.3 答题示例
    4. 20.4 关键词联想

20.List初始化效率比较


20.1 题目

//代码1:
List<int> list = new List<int>();
for (int i = 0; i < 50; i++)
{
    list.Add(i);
}

//代码2:
List<int> list2 = new List<int>(50);
for (int i = 0; i < 50; i++)
{
    list2.Add(i);
}

以上代码,谁的效率更高?为什么?


20.2 深入解析

代码2的效率更高。

因为List的本质是数组,在初始化时,如果不明确指定分配多少容量,它会不断扩容。扩容会带来效率的降低和垃圾的产生。

详细解释

  1. 效率的降低

    • 扩容时,List需要将旧数组中的元素复制到一个新的更大的数组中。这个过程称为“搬家”,需要时间和资源。
    • 默认情况下,当List的容量不够时,容量会按照一定的倍数增长(通常是两倍)。这个过程需要不断地重新分配内存并复制数据,从而导致性能的降低。
  2. 垃圾的产生

    • 每次扩容时,旧数组就变成了垃圾,需要垃圾回收机制来处理。这会增加垃圾回收的负担,进一步影响性能。
  • 在代码1中,List<int> list1 是在没有指定初始容量的情况下创建的。当添加元素时,List 需要不断地扩容。
  • 在代码2中,List<int> list2 在创建时指定了初始容量 50。因此可直接分配足够空间容纳本次循环中的全部元素,避免扩容。

总结

通过在创建 List 时指定初始容量,可以显著提高性能,避免不必要的扩容操作和垃圾产生。因此,在可以预估集合大小的情况下,最好在初始化时指定容量,这样可以优化性能,提高效率。


20.3 答题示例

代码2效率更高。原因是 List<T> 的底层是数组,若未指定容量(如代码1),在添加元素过程中会不断触发自动扩容,每次扩容都需要:

  • 分配新数组(通常是原容量的2倍)
  • 将旧数组内容拷贝到新数组
  • 回收旧数组造成 GC 压力

代码2通过 new List<int>(50) 预先分配了容量,避免了扩容开销,因此性能更优,尤其在循环次数较大时优势更明显。

优化建议:能预估容量的集合建议提前指定容量大小


20.4 关键词联想

  • List扩容机制
  • 内存拷贝(CopyTo)
  • GC压力
  • 初始化容量
  • 性能优化
  • Add引发Realloc
  • 集合性能提升策略
  • 构造函数容量参数


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏