Я фактично написав повідомлення в блозі на цю тему 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
операції.
Список літератури