Дополнительно
Зачем начинать список ArrayList с начальной емкости?
Обычным конструктором ArrayList
является:
ArrayList<?> list = new ArrayList<>();
Но есть также перегруженный конструктор с параметром для его начальной емкости:
ArrayList<?> list = new ArrayList<>(20);
Почему полезно создавать ArrayList
с начальной емкостью, если мы можем добавлять к нему все, что захотим?
147
11
Если вы заранее знаете, какого размера будет
ArrayList
, эффективнее указать начальную емкость. Если этого не сделать, внутренний массив придется многократно перераспределять по мере роста списка.Чем больше конечный список, тем больше времени вы экономите, избегая перераспределения.
Тем не менее, даже без предварительного распределения, вставка
n
элементов в конецArrayList
гарантированно займет времяO(n)
. Другими словами, добавление элемента - это амортизированная операция постоянного времени. Это достигается тем, что каждое перераспределение увеличивает размер массива экспоненциально, обычно в1.5
раза. При таком подходе общее количество операций может быть показано какO(n)
.Потому что
коллекции
является динамическое изменение размера массива структура данных, которая означает, что она реализуется как массив с исходным (по умолчанию) фиксированного размера. При этом заполняется массив будет продлен до двойного размера. Эта операция является дорогостоящей, поэтому вы хотите как можно меньше.Поэтому, если вы знаете, что ваш верхний предел составляет 20 пунктов, то при создании массива с начальной длиной 20 лучше, чем по умолчанию, скажем, 15 и затем изменить ее размер на 15*2 = 30` и использовать только 20, а тратить циклы на расширение.
С. П. - Как AmitG говорит, коэффициент расширения является определенной реализацией (в данном случае
(oldCapacity * 3)/2 + 1
)По умолчанию размер списка массивов равен 10.
Поэтому если вы собираетесь добавить 100 или более записей, вы можете увидеть накладные расходы на перераспределение памяти.
Поэтому если у вас есть представление о количестве элементов, которые будут храниться в Arraylist, лучше создать Arraylist с этим размером, а не начинать с 10 и затем увеличивать его.
Я написал блог по теме 2 месяца назад. Статья для C#и#39;список З в
<Т>
Но Java'ыколлекции
имеет очень похожую реализацию. Посколькуколлекции
реализуется с помощью динамического массива, он увеличивается в размерах по требованию. Так что причин для конструктора потенциал для оптимизации.Когда один из этих операции resizings возникает, коллекции копирует содержимое массива в новый массив, который является вдвое большей емкостью, чем старый. Эта операция выполняется в О(Н) время.
Пример
Вот пример, как
коллекции
будет увеличиваться в размерах:Так что список начинается с емкостью
10
, Когда 11-й элемент добавляется это увеличение на 50% + 1на
16. На 17-й пункт в
коллекцииснова увеличивается до
25и так далее. Теперь рассмотрим пример, где мы'вновь создать список, в котором нужные способности уже известны как
1000000. Создание
коллекциибез конструктора размер будет называть класса ArrayList.добавить
1000000
времена, которые берет О(1) обычно, либо о(н) на размер.Сравните это с помощью конструктора, а затем звонит в коллекцию ArrayList.добавить`, который гарантированно работает в О(1).
На Java против c#
Java-это, как указано выше, начиная с
10
и растет каждый размер на 50% + 1. В C# начинается на
4и увеличивается гораздо более агрессивно, удваивая на каждом размер. В
1000000добавляет примере выше для операций c# использует
3097084`.Ссылки
Установка начального размера списка ArrayList, например,
ArrayList(100)
, уменьшает количество повторных выделений внутренней памяти.Пример:
Как видно из приведенного выше примера,
ArrayList
может быть расширен, если это необходимо. Что здесь не показано, так это то, что размер ArrayList обычно удваивается (хотя обратите внимание, что новый размер зависит от вашей реализации). Следующее цитируется по Oracle:Очевидно, что если у вас нет представления о том, какой диапазон вы будете хранить, установка размера, вероятно, не будет хорошей идеей - однако, если у вас есть конкретный диапазон, установка начальной емкости увеличит эффективность использования памяти.
ArrayList может содержать много значений, и когда делаешь большие первоначальные вставок вы можете сказать ArrayList для выделить большой объем памяти для начала, чтобы не тратить циклы процессора, когда он пытается выделить больше места для следующего элемента. Таким образом, чтобы выделить определенное пространство в начале более эффективной.
Это позволит избежать возможные усилия для перераспределения для каждого объекта.
создан новый объект внутри
[]
- это.<БР> JVM необходима усилия, чтобы создать новый объект[]при добавлении элемента в коллекцию ArrayList. Если вы Don'т иметь выше код(любой алгоритм вы думаете) для перераспределения затем каждый раз, когда вы вызываете
класса ArrayList.добавить ()", затем " новый объект[]должен быть создан, который бессмысленно и мы теряем время для увеличения размера по 1 для каждого объекты, которые будут добавлены. Так что лучше, чтобы увеличить размер объекта[]
с помощью следующей формулы.<БР> (С JSL использовал формулу прогнозирования, приведенные ниже, динамично растущей коллекции, а не увеличивается на 1 каждый раз. Потому что расти он принимает усилия для JVM)Я'd для его оптимизации. Класса ArrayList без первоначального емкость будет ~10 пустых строк и будет расширяться, когда вы делаете добавить.
Иметь список с точно число элементов, вам нужно позвонить метода trimtosize()
Я думаю, что в каждой коллекции создается со значением емкости инициализации на "10 и". Так что в любом случае, если вы создаете объект ArrayList без создания потенциала в конструктор, то он будет создан со значением по умолчанию.
Как на мой опыт с
коллекции
, давая начальная емкость является хорошим способом, чтобы избежать расходов на перераспределение. Но он несет в себе предостережение. Все предложения, упомянутые выше, говорят, что нужно предоставить первоначального потенциала только тогда, когда грубая оценка числа элементов известно. Но когда мы пытаемся предоставить первичную емкость без какой-либо идеи, объем памяти, зарезервированных и неиспользуемых будет отходов, как он может никогда не потребоваться после того, как список заполняется необходимое количество элементов. Я хочу сказать, мы можем быть прагматиками в начале при выделении мощности, а затем найти умный способ познания требуется минимальная мощность во время выполнения. Класса ArrayList содержит метод, называемыйensureCapacity(тип int minCapacity)
. Но тогда, стоит найти умный способ...Я испытал ArrayList с С и без initialCapacity и меня удивляют результатом <БР/> Когда я LOOP_NUMBER до 100 000 или меньше, в итоге получается, что установка initialCapacity является эффективным. <БР>
<БР/> Но когда я установил LOOP_NUMBER до 1000000 результатом изменения: <БР/>
<БР/> Наконец, я не мог'т выяснить, как это работает?! <БР/> Пример кода:
Я испытал на Windows8.1 и jdk1.7.0_80