Я фактически написал сообщение в блоге на тему 2 месяца назад. Статья предназначена для C #, List<T>
но Java ArrayList
имеет очень похожую реализацию. Так ArrayList
как реализован с использованием динамического массива, он увеличивается в размере по требованию. Поэтому причина для конструктора емкости - в целях оптимизации.
Когда происходит одна из этих операций изменения размеров, ArrayList копирует содержимое массива в новый массив, который в два раза больше емкости старого. Эта операция выполняется за O (n) времени.
пример
Вот пример того, как ArrayList
размер увеличится:
10
16
25
38
58
... 17 resizes ...
198578
297868
446803
670205
1005308
Таким образом, список начинается с емкости 10
, при добавлении 11-го элемента он увеличивается 50% + 1
до 16
. На 17-м пункте ArrayList
снова увеличен до 25
и так далее. Теперь рассмотрим пример, в котором мы создаем список, в котором желаемая емкость уже известна как 1000000
. Создание конструктора ArrayList
без размера вызовет ArrayList.add
1000000
время, которое обычно занимает O (1) или O (n) при изменении размера.
1000000 + 16 + 25 + ... + 670205 + 1005308 = 4015851 операций
Сравните это, используя конструктор, а затем вызов, ArrayList.add
который гарантированно будет выполняться в O (1) .
1000000 + 1000000 = 2000000 операций
Java против C #
Java как и выше, начиная с 10
каждого размера и увеличивая его 50% + 1
. C # начинается 4
и увеличивается гораздо агрессивнее, удваивается при каждом изменении размера. Добавленный 1000000
пример сверху для C # использует 3097084
операции.
Ссылки