Ответ
ArrayList динамически расширяется за счет изменения размера своего внутреннего массива (Object[] elementData).
Механизм увеличения емкости:
- При добавлении элемента (например, через
add()) проверяется, достаточно ли свободных ячеек в массиве. - Если емкости недостаточно, запускается процесс
grow():- Создается новый массив большего размера.
- Все элементы копируются из старого массива в новый с помощью
Arrays.copyOf. - Ссылка
elementDataначинает указывать на новый массив. - Старый массив становится доступным для сборщика мусора.
Формула увеличения: По умолчанию новый размер вычисляется как newCapacity = oldCapacity + (oldCapacity >> 1). Это увеличение в 1.5 раза (побитовый сдвиг вправо на 1 равен целочисленному делению на 2).
Пример:
// Начальная емкость по умолчанию — 10
ArrayList<Integer> list = new ArrayList<>();
// Добавление 11-го элемента вызовет расширение
for (int i = 0; i < 11; i++) {
list.add(i); // При i == 10 произойдет grow()
}
Почему так сделано? Увеличение в 1.5 раза — это компромисс между производительностью (слишком частое копирование) и расходом памяти (слишком большой неиспользуемый запас). Начальную емкость можно задать конструктором ArrayList(int initialCapacity), чтобы минимизировать количество расширений, если известен примерный размер данных.