List<> 容量返回的项目多于添加的项目

Posted

技术标签:

【中文标题】List<> 容量返回的项目多于添加的项目【英文标题】:List<> Capacity returns more items than added 【发布时间】:2011-01-29 22:03:37 【问题描述】:

List&lt;T&gt; 上有几个属性似乎与列表中的项目数有关 - CapacityCount(作为属性和方法存在)。这非常令人困惑,尤其是与只有LengthArray 相比。

我正在使用List.Capacity,但它给出了意想不到的结果:

List <string> fruits = new List<string>();
fruits.Add("apple");
fruits.Add("orange");
fruits.Add("banana");
fruits.Add("cherry");
fruits.Add("mango");
Console.WriteLine("the List has 0 items in it.", fruits.Capacity);

当我运行它时,控制台显示:

列表中有 4 个项目。

当我只添加了 5 个项目时,我不明白为什么它显示 Capacity 为 8。

【问题讨论】:

en.wikipedia.org/wiki/Dynamic_array 复制:***.com/questions/2247773 一个相关的link 包含在这个问题的答案列表中可能很有趣。 我不觉得这是一个重复的问题。您指出的问题是关于初始化容量。那里提供的答案只说明了为什么要或不想初始化它的容量属性。他们没有回答“为什么它显示容量为 8,而我只添加了 7 个项目”。正如这里所指出的,我的问题是容量与计数之一。 几乎所有语言都存在类似的混淆 - 请参阅 ***.com/questions/300522/… 了解其他“集合中的项目数”属性。 【参考方案1】:

为了理解为什么它更大,你需要了解List&lt;T&gt; 在内部是如何工作的。在内部,List&lt;T&gt; 使用一个数组(即T[])来存储其内容。

这个数组以 4 个元素的大小开始,所以相当于说T[] array = new T[4]。当您将一个项目添加到List&lt;T&gt; 时,它会存储在数组中:array[0] 中的第一项,array[1] 中的第二项,等等。但是,第五项无法放入此数组中,因为它只有四个元素长。而且由于数组的长度在创建后无法更改,唯一的选择是获取数组的内容并将其移动到一个足够大的 new 数组以容纳它第五项也是如此。 List&lt;T&gt; 的实现选择在每次空间不足时将数组缓冲区的大小加倍,因此为了适应第五个项目,它将数组容量加倍到 8。然后是 16,依此类推。

它为什么选择加倍可能有很好的数学支持,这可能是昂贵的复制操作(不想太频繁地分配新缓冲区)和浪费空间之间的一个很好的折衷方案。我相信,通过加倍,内存浪费永远不会超过 50%,并且需要分配新数组的次数会以对数方式减少。

【讨论】:

【参考方案2】:

容量与列表的项目数不同。默认情况下,所有语言中实现良好的列表容器分配的内存比它们保存当前条目数所需的内存要多。这是因为在某些时候分配更大的内存块比每次添加一项时为多一项分配内存更有效。

【讨论】:

【参考方案3】:

这里是容量属性from MSDN的完整解释:


Capacity 是需要调整大小之前List&lt;T&gt; 可以存储的元素数量,而CountList&lt;T&gt; 中实际存在的元素数量.

Capacity 总是大于或等于 Count。如果在添加元素时 Count 超过了容量,则通过在复制旧元素和添加新元素之前自动重新分配内部数组来增加容量。

可以通过调用TrimExcess() 方法或显式设置Capacity 属性来减少容量。当显式设置Capacity的值时,内部数组也会重新分配以容纳指定的容量,并复制所有元素。

检索此属性的值是 O(1) 操作;设置属性是一个 O(n) 操作,其中 n 是新容量。

【讨论】:

【参考方案4】:

要添加到其他答案,List 在逐个添加项目时的默认行为是从容量 4 开始,并在列表变满时将其加倍。这就解释了 8 的容量。

【讨论】:

【参考方案5】:

列表的Capacity 表示列表当前为当前对象和要添加到其中的对象预留了多少内存。列表的Count 是实际添加到列表中的项目数。

【讨论】:

以上是关于List<> 容量返回的项目多于添加的项目的主要内容,如果未能解决你的问题,请参考以下文章

返回具有 List<t> 中不存在的项目的 List<t> [重复]

如何将项目添加到 List<T> 的开头?

#yyds干货盘点# Collection - ArrayList 源码解析

如何将 List<T> 初始化为给定大小(而不是容量)?

Java ArrayList源码剖析

ArrayList在js里面怎么添加数据