Список <> Способность возвращает больше объектов, чем добавленный

Существует несколько свойств на List<T> это, кажется, связано с количеством объектов в списке - Capacity, Count (который присутствует как свойство и метод). Это довольно сбивает с толку особенно по сравнению с Array это имеет просто Length.

Я использую 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.

Я не понимаю почему его показ a Capacity из 8, когда я только добавил 5 объектов.

13
задан Alexei Levenkov 18 June 2016 в 02:02
поделиться

5 ответов

Емкость списка представляет, какой объем памяти в настоящее время выделен для текущие объекты и объекты, которые будут добавлены к нему. Счетчик списка - это количество элементов, фактически добавленных в список.

34
ответ дан 1 December 2019 в 17:17
поделиться

Вот полное объяснение свойства емкости из MSDN :


Вместимость количество элементов, которые List может сохранить до того, как потребуется изменение размера, а Count - это количество элементов, которые фактически находятся в List .

Емкость всегда больше или равна Count. Если количество превышает емкость при добавлении элементов, емкость увеличивается за счет автоматического перераспределения внутреннего массива перед копированием старых элементов и добавлением новых элементов.

Емкость можно уменьшить, вызвав метод TrimExcess () или явно задав свойство Capacity. Если значение Capacity установлено явно, внутренний массив также перераспределяется для размещения указанной емкости, и все элементы копируются.

Получение значения этого свойства - операция O (1); установка свойства - это операция O (n), где n - новая емкость.

17
ответ дан 1 December 2019 в 17:17
поделиться

Чтобы добавить к другим ответам, поведение списка по умолчанию при добавлении элементов по одному - начинать с емкости 4 и удваивать ее каждый раз, когда список становится полным. Это объясняет емкость 8.

8
ответ дан 1 December 2019 в 17:17
поделиться

Чтобы понять, почему он больше, вам нужно понять, как List работает внутри. Внутри List использует массив (так T [] ) для хранения своего содержимого.

Этот массив начинается с 4 элементов, что эквивалентно выражению T [] array = new T [4] . Когда вы добавляете элемент в List , он сохраняется в массиве: первый элемент в array [0] , второй в array [1] и т. Д. Пятый элемент, однако, не может поместиться в этот массив, так как он состоит всего из четырех элементов. А поскольку длину массива нельзя изменить после его создания, единственный вариант - взять содержимое массива и переместить его в новый массив, который достаточно велик, чтобы вместить пятый пункт тоже. Реализация List выбирает удваивать размер буфера массива каждый раз, когда в нем заканчивается пространство, поэтому, чтобы уместить пятый элемент, он удваивает емкость массива до 8. Затем 16, и так на.

Вероятно, существует хорошее математическое обоснование того, почему он выбирает удвоение, вероятно, это хороший компромисс между дорогостоящими операциями копирования (не нужно слишком часто выделять новый буфер) и потраченным впустую пространством. Я считаю, что при удвоении потери памяти никогда не превышают 50%, и количество раз, когда необходимо выделить новый массив, уменьшается логарифмически.

8
ответ дан 1 December 2019 в 17:17
поделиться

Емкость - это не то же самое, что количество элементов в списке. Хорошо реализованные контейнеры списков во всех языках по умолчанию выделяют больше памяти, чем им нужно для сохранения текущего количества элементов. Это происходит потому, что эффективнее выделять больший кусок памяти некоторое время, чем выделять память для еще одного элемента каждый раз, когда вы его добавляете.

0
ответ дан 1 December 2019 в 17:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: