我正在尝试执行以下操作:
int count = 50;
List<float> myList = new List<float>(50);
output[0] = 0.0f;
Run Code Online (Sandbox Code Playgroud)
但我得到错误:
ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
Run Code Online (Sandbox Code Playgroud)
显然,我误解了List(或者任何其他集合?)的初始容量是什么.有人可以向我解释一下初始容量是多少?
列表底部有一个数组.这样可以减少内存重新分配的数量.添加到50个元素.这需要时间和内存,并提供垃圾收集器的功能.
这就是为什么List(T).Capacity是一个东西.
Method A: Dictionary, no capacity
Time: 1350 ms
Method B: Dictionary, has capacity
Time: 700 ms
Method C: Dictionary, const capacity
Time: 760 ms
Method D: Dictionary, over-large capacity
Time: 1005 ms
Method E: List, no capacity
Time: 1010 ms
Method F: List, accurate capacity
Time: 575 ms
Run Code Online (Sandbox Code Playgroud)
因此,当您添加100个元素时,预分配似乎只需要一半的时间.虽然我不是过早优化的粉丝,但如果你知道你的列表有多大,那么给CLR一个暗示是值得的.
首先,为什么会出现异常:
通过定义初始容量,您只需指定列表在需要调整大小之前可以存储的元素数量。
这并不意味着您的列表中有可访问的索引。您的列表仍然是空的,因此当您这样做时:
myList[0] = 0.0f;
Run Code Online (Sandbox Code Playgroud)
你会得到一个例外,但如果你这样做:
List<float> myList = new List<float>(50);
myList.Add(0);
myList[0] = 2.0f;
Run Code Online (Sandbox Code Playgroud)
现在你不会得到异常,因为索引处有一个元素0。
现在问题的第二部分,容量实际上意味着什么:
参见:List<T>.Capacity属性:
容量是在需要调整大小之前列表可以存储的元素数量,而计数是列表中实际存在的元素数量。
容量始终大于或等于计数。如果添加元素时计数超过容量,则在复制旧元素并添加新元素之前,通过自动重新分配内部数组来增加容量。
该列表是动态的。它可以在运行时动态添加项目和删除项目。
List 实现使用底层数组来存储列表的项目。底层数组的长度称为列表的容量。
列表中的每个项目都存储在底层数组中。
当尝试将新项目添加到列表中并且基础数组中不再有空白空间时,将创建一个新的更大的数组。
旧数组中的所有项目都将移动到新数组,新数组还包含更多空间用于新项目。
然后新数组将被设置为列表的底层数组(旧数组将被处理)。
这种分配新数组然后将项目从旧数组移动到新数组的操作成本很高(性能方面)。
因此,如果您从一开始就知道要添加到列表中的项目数。那么您可以使用具有所需初始容量的基础数组创建列表。
因此,您的列表在运行时分配新的底层数组的机会会更小。您可以通过调用List(T) 构造函数(int32)
设置底层数组的初始长度您可以通过调用List(T).Capacity 属性
来获取当前数组的长度
| 归档时间: |
|
| 查看次数: |
4139 次 |
| 最近记录: |