列表>>容量返回的项目多于添加的项目
List
上有几个属性似乎与列表中的项目数量相关 - Capacity
、Count
(存在)作为属性和方法)。这是相当令人困惑的,尤其是与只有 Length
的 Array
相比。
我正在使用 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);
当我运行此命令时,控制台显示:
the List has 4 items in it.
我不明白为什么它显示的 Capacity
为 8,当我只添加了5个项目。
There are several properties on List<T>
that seem to be related to number of items in the list - Capacity
, Count
(which is present as a property and a method). This is quite confusing especially compared with Array
that has just Length
.
I'm using List.Capacity
but it gives unexpected result:
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);
when I run this the Console displays:
the List has 4 items in it.
I don't understand why its showing a Capacity
of 8, when I only added 5 items.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
列表的
Capacity
表示列表当前为当前对象和要添加到其中的对象留出多少内存。列表的Count
是实际添加到列表中的项目数。The
Capacity
of the list represents how much memory the list currently has set aside for the current objects and objects to be added to it. TheCount
of the list is how many items have actually been added to the list.以下是来自 MSDN 的容量属性的完整说明:
容量 是。
List
在需要调整大小之前可以存储的元素数量,而 Count 是List
中实际存在的元素数量>列表容量始终大于或等于计数。如果添加元素时计数超过容量,则在复制旧元素并添加新元素之前,通过自动重新分配内部数组来增加容量。
可以通过调用 TrimExcess() 方法或通过设置来减少容量明确的容量属性。当明确设置Capacity的值时,内部数组也会被重新分配以容纳指定的容量,并复制所有元素。
检索该属性的值是一个 O(1) 操作;设置属性是一个 O(n) 操作,其中 n 是新容量。
Here's the full explanation for the Capacity property from MSDN:
Capacity is the number of elements that the
List<T>
can store before resizing is required, while Count is the number of elements that are actually in theList<T>
.Capacity is always greater than or equal to Count. If Count exceeds Capacity while adding elements, the capacity is increased by automatically reallocating the internal array before copying the old elements and adding the new elements.
The capacity can be decreased by calling the TrimExcess() method or by setting the Capacity property explicitly. When the value of Capacity is set explicitly, the internal array is also reallocated to accommodate the specified capacity, and all the elements are copied.
Retrieving the value of this property is an O(1) operation; setting the property is an O(n) operation, where n is the new capacity.
为了理解为什么它更大,您需要了解
List
内部是如何工作的。在内部,List
使用数组(即T[]
)来存储其内容。该数组一开始的大小为 4 个元素,因此相当于
T[] array = new T[4]
。当您向List
添加项目时,它会存储在数组中:第一个项目位于array[0]
中,第二个项目位于array[ 1]
等。但是,第五项无法放入此数组,因为它只有四个元素长。由于数组的长度在创建后无法更改,因此唯一的选择是获取数组的内容并将其移动到一个足够大以容纳该数组的新数组中第五项也是如此。List
的实现选择在每次空间不足时将数组缓冲区的大小加倍,因此为了容纳第五项,它将数组容量加倍到 8。然后是 16,以及很快。为什么它选择加倍可能有很好的数学支持,这可能是昂贵的复制操作(不想太频繁地分配新缓冲区)和浪费的空间之间的一个很好的折衷方案。我相信,通过加倍,内存浪费永远不会超过 50%,并且需要分配新数组的次数呈对数减少。
In order to understand why it is bigger, you need to understand how
List<T>
works internally. Internally, aList<T>
uses an array (soT[]
) to store its contents.This array starts off with a size of 4 elements, so equivalent to saying
T[] array = new T[4]
. When you add an item to aList<T>
, it is stored in the array: the first item inarray[0]
, the second inarray[1]
, etc. The fifth item, however, can't fit into this array, as it's only four elements long. And because the length of an array can't be changed after it has been created, the only option is to take the contents of the array and move it to a new array that is large enough to hold that fifth item as well. The implementation ofList<T>
chooses to double the size of the array buffer each time it runs out of space, so to fit the fifth item, it doubles the array capacity to 8. Then 16, and so on.There is probably good mathematical backing on why it chooses to double, it's probably a good compromise between the expensive copy operations (don't want to allocate a new buffer too often) and wasted space. By doubling, the memory waste is never over 50% and the amount of times a new array needs to be allocated decreases logarithmically, I believe.
要添加到其他答案,列表在逐个添加项目时的默认行为是从容量 4 开始,并在列表变满时将其加倍。这就解释了8的容量。
To add to the other answers, the default behaviour of List when adding items one by one is to start with a capacity of 4 and double it whenever the list becomes full. This explains the capacity of 8.
容量与列表的项目数不同。默认情况下,所有语言中实现良好的列表容器都会分配比保存当前条目数所需的更多内存。这是因为有时分配更大的内存块比每次添加一项时再为一项分配内存更有效。
Capacity is not the same as the item count of the list. Well implemented list containers in all languages by default allocate more memory than they need to save the current number of entries. This is because it is more efficient to allocate a bigger chunk of memory some of the time than to allocate memory for one more item every time you add one.