Различие между емкостью списка массивов и размером массива

Я прочитал приведенный ниже фрагмент в Core Java I book.

выделение списка массивов как новый ArrayList (100) / / емкость 100

Не то же самое, что выделение нового массива как новый сотрудник[100] / / Размер 100

существует важное различие между емкостью списка массивов и размером матрица. Если вы выделяете массив со 100 записями, то массив имеет 100 слотов, готовых для использования. Список массивов вместимостью 100 элементов может содержать 100 элементов (и, на самом деле более 100, за счет дополнительных перераспределений); но в начале даже после первоначального построения список массивов не содержит элементов вообще.

когда я увидел список массивов исходного кода, конструктор создает массив объектов заданной емкости, который готов содержать элементы заданной емкости (ниже приведен фрагмент кода).

public ArrayList(int initialCapacity) {
     super();
     if (initialCapacity < 0)
         throw new IllegalArgumentException("Illegal Capacity: "+
                                            initialCapacity);
     this.elementData = new Object[initialCapacity];
 }

Я не могу понять фактическую разницу, что автор упомянул в приведенном выше тексте.

6 ответов


если вы выделяете новый массив с arr = new Employee[100], размер этого массива (arr.length) будет 100. Он имеет 100 элементов. Все элементы изначально нулевые (так как это массив ссылок на объекты), но все же есть 100 элементов.

если вы делаете что-то вроде list = new ArrayList <Employee>(100), а list.size(), вы получите 0. В списке нет элементов.

внутренне, это правда, что ArrayList выделяет достаточно места, чтобы поместить 100 элементов, прежде чем он должен расширить его емкость, но это внутренняя деталь реализации, и список представляет вам свое содержимое как "нет сохраненных элементов". Только если вы на самом деле list.add(something), у вас будут элементы в списке.

поэтому, хотя список выделяет хранилище заранее, API, с которым он взаимодействует с программой, говорит вам, что в нем нет элементов. Нулевые элементы в его внутреннем массиве недоступны для вас - вы не можете их получить или изменить.


ArrayList - это всего лишь один из способов представления абстрактного списка, а емкость ArrayList-это деталь реализации того, как система реализует логический список.

ArrayList хранит элементы списка, используя фактический массив " под обложками."Фактическая реализация массива в памяти компьютера имеет определенный размер, когда он выделяется; этот размер является емкостью ArrayList. ArrayList эмулирует список переменного размера, сохраняя логическую длину список в дополнение к массиву фиксированной длины. Таким образом, если у вас есть ArrayList с емкостью 10, которая содержит 4 логических элемента, ArrayList может быть представлен как length и array

(4) | e1 / e2 / e3 | e4| __ | __ | __| __ | __ | __ |

где (4) - логическая длина списка, а "_ _ " - данные, которые игнорируются, поскольку они не являются частью логического списка. Если вы попытаетесь получить доступ к 5-му элементу этого ArrayList, он выдаст исключение, потому что он знает, что Пятый элемент не инициализирован. Если мы добавим дополнительный элемент e5 в список, ArrayList станет

(5) | e1 / e2 / e3 | e4 | e5| __ | __ | __ | __ | __ |

обратите внимание, что емкость не изменилась, в то время как длина логической, поскольку основной массив еще может обрабатывать все данные в логическую.

Если вам удастся добавить более десяти элементов в этот список, ArrayList не будет ломать. ArrayList-это абстракция, совместимая со всеми операциями массива. Скорее, ArrayList изменяет свою емкость, когда его логическая длина превышает исходную емкость. Если бы мы добавили элементы (a1, a2,..., a7) в приведенном выше списке результирующий ArrayList может выглядеть как

(12) | e1 | e2 | e3 | e4 | e5 / a1 | a2 | a3 | a4 | a5 | a6 | a7| __ | __ | __ | __ | __ | __ | __ | __ |

с емкостью 20.

Как только вы имеете созданный ArrayList, вы можете игнорировать емкость во всех последующих программах; логика не изменяется. Однако производительность системы при определенных видах операций может быть затронута. Например, увеличение емкости может потребовать выделения большего массива, копирования первого массива во второй, а затем выполнения операций. Это может быть довольно медленно по сравнению с, например, той же операцией в связанном списке. Таким образом, разумно выбрать способность ArrayList должен быть больше или, по крайней мере, сопоставим с фактическим количеством элементов, ожидаемых в реальной среде выполнения.


если вы создадите новый массив myArray = new Object[100] тогда вы можете читать и писать из myArray[0] to myArray[99] (и вы найдете ее полное null).

при создании ArrayList myList = new ArrayList(100) тогда попробуйте и get или set любые элементы, вы получите IndexOutOfBoundsException, потому что List пусто, пока вы add что-то есть.

в общем, массив размером 100 первоначально будет содержать 100 nulls, но List будет пустым.


Это просто кажется плохо сформулированным и потенциально неправильным, если я не понимаю его правильно.

Я считаю, что он пытается сказать, что существует разница между начальной емкостью ArrayList и начальным размером ArrayList.

List<Employee> employees = new ArrayList<>(100);
int size = employes.size();

в размере будет 0, а начальная емкость 100.

вы правильно читаете исходный код.


разница между фиксированный размер контейнер (структура данных) и переменной размере контейнер.

An массив это фиксированный размер контейнер, количество элементов, которые он содержит, устанавливается при создании массива и никогда не изменяется. (Когда массив будет создан, все эти элементы будут иметь некоторое значение по умолчанию, например, null для ссылочных типов или 0 для ints, но все они будут там в массиве: вы можете индекс каждого.)

A список это переменной размере container, количество элементов в нем может изменяться, от 0 до столько, сколько вы хотите (при условии ограничений реализации). После создания количество элементов может либо увеличиваться, либо уменьшаться. В любое время вы можете получить любой элемент по его индексу.

но концепция Java List фактически является интерфейсом и его можно реализовать различными способами. Таким образом, ArrayList, LinkedList, etc. Существует структура данных " за " списком, чтобы фактически удерживать элементы. И сама эта структура данных может быть фиксированным размером или переменным размером, и в любой момент времени может иметь точный размер числа элементов в списке, или она может иметь некоторые extra "буферного" пространства.

на LinkedList, например, всегда имеет в своей базовой структуре данных точно такое же количество "мест для элементов", как и в списке, который он представляет. Но ... --1--> использует массив фиксированной длины в качестве резервного хранилища.

на ArrayList, в любой момент времени количество элементов в списке может отличаться от количества элементов, которые может содержать массив. Эти "дополнительные" места для элементов просто содержат нули или 0 или что-то еще, но ArrayList не дает вам доступ к тем местам. Как вы добавляете элементы в ArrayList они занимают больше места в базовом массиве, пока, наконец, основной массив заполнен. The далее элемент вы добавляете к ArrayList вызывает выделение совершенно нового массива фиксированного размера - несколько большего, чем "текущий" массив, и все элементы списка, скопированные в него (исходный массив отбрасывается). Чтобы предотвратить эту дорогостоящую операцию (выделение и копирование) слишком часто, новый массив больше, чем текущий массив (в некотором отношении), и поэтому имеет элементы, которые в это время не будут содержать элементы списка - они пусты (null или 0).

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

на в размере из списка-количество элементов в нем. The емкости из списка-это количество элементов, которые может содержать структура резервных данных в это время. Размер будет меняться по мере добавления или удаления элементов в списке. Емкость изменится, когда это потребуется для реализации списка, который вы используете. (Размер, конечно, никогда не будет больше емкости.)

(кстати, для контейнеров фиксированного размера в размере часто называют длина, таким образом, массивы имеют свойство длина и строки имеют метод длина(). Разные языки-иногда даже один и тот же язык - используют" размер "и" длину " непоследовательно, но они всегда означают в размере, и термин "емкость" всегда используется для размера/длины базовой структуры данных.)


давайте использовать реальный пример жизни. Рассмотрим восемнадцатиместный автобус, вместимость которого составляет восемнадцать пассажиров. Размер пассажиров в любой момент времени может быть менее восемнадцати, но не более. Когда число пассажиров составляет восемнадцать, другой пассажир не может быть размещен.

в ArrayList емкость имеет что-то общее с нашей шиной в том, что она определяет количество элементов, которые могут поместиться. В отличие от нашего автобуса, однако, емкость расширяется для размещения количество элементов до целого числа.МАКСИМАЛЬНОЕ ЗНАЧЕНИЕ.

то же самое касается размера, как и наша шина, размер элементов в списке не может превышать емкость. Только представьте, если 50 пассажиров едут восемнадцать-местный автобус! Ты точно не хочешь быть в этом автобусе.