删除列表中计数和容量之间的距离



>我已经创建了一个列表并为列表赋值。

List<int> array = Enumerable.Repeat(0, max).ToList();

最终输出是正确的。但列表中的两个标准(计数和容量(彼此不同。

例如:容量为:2048,计数为:1559。 为什么?

如何消除这个距离?

你可以参考布尔萨克米兰的答案进行解释。

对于这个问题:

如何消除这个距离?

您可以通过创建自己的初始容量列表来修复容量,如下所示:

var list = new List<int>(max);
list.AddRange(Enumerable.Repeat(0, max));

演示。

容量是 List 在需要调整大小之前可以存储的元素数,而 Count 是实际在列表中的元素数。

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

基本上你想用的是TrimExcess

容量设置为列表中元素的实际数量(如果该数字小于阈值(。

此方法可用于最小化集合的内存开销(如果不会向集合添加新元素(。但是,重新分配和复制大型列表的成本可能相当高,因此,如果列表的容量超过 90%,则 TrimExcess 方法不执行任何操作。这避免了以相对较小的收益产生大量的重新分配成本。

这是由于List<T>实现的方式。淡化整个事情,List<T>有一个私有数组变量,其中包含您添加的所有项目。现在,数组的大小是固定的。因此,MS 开始时最小大小为 4。这就是您的初始阵列大小。因此,以下代码行在内部创建一个大小为 4 的数组。

List<int> test = new List<int>();
// internally
int[] _items = new int[4];

当我们开始添加项目时,List 类会在内部计算其内部数组是否足够大。在上面的列表中,添加了第 5 个元素时,它显然不能将其存储在数组中。因此,它会创建一个新数组并复制其中的所有内容。新的数组大小是根据类中名为EnsureCapacity的私有方法决定List<T>。类将其发送到current array size + 1在本例中为 5。然后,此方法在内部将数字加倍并创建一个新数组。因此,将创建一个大小为 8 的新数组。在第 9 项上,它变为 16,依此类推。

这将持续到我们达到 2GB 标记(.Net 中的最大对象大小(为止。

虽然容量高于列表大小没有害处,但如果您正在处理内存敏感应用程序,则可以在确定不会添加新项目时调用TrimExcess(它很昂贵(。或者,使用自行设置容量的构造函数。

让我感到困惑的一件事是ToList扩展方法调用List<T>构造函数,IEnumerable<T>作为参数。此构造函数声称容量将与给定的集合大小相同,但不知何故并非如此。