Ответ
Начальная ёмкость (capacity) внутреннего массива ArrayList при создании через конструктор без параметров равна 0, а не 10, начиная с Java 8. Массив создаётся лениво, при первом добавлении элемента.
Механизм работы:
- Конструктор
ArrayList(): Инициализирует внутренний массивelementDataпустой константойDEFAULTCAPACITY_EMPTY_ELEMENTDATA.// Java 8+ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // {} (пустой массив) } - Первое добавление (
add(E e)): При первом вызовеadd()проверяется, является ли массив пустой константой. Если да, то ёмкость увеличивается до значенияDEFAULT_CAPACITY, которое равно 10.private static final int DEFAULT_CAPACITY = 10; - Последующее увеличение: Когда внутренний массив заполняется, его ёмкость увеличивается по формуле
newCapacity = oldCapacity + (oldCapacity >> 1), что примерно равно увеличению в 1.5 раза.
Конструкторы для явного указания ёмкости:
// Создаёт ArrayList с начальной ёмкостью 20
ArrayList<String> listWithCapacity = new ArrayList<>(20);
// Создаёт список, инициализированный другой коллекцией.
// Начальная ёмкость равна размеру переданной коллекции.
ArrayList<String> listFromCollection = new ArrayList<>(someOtherList);
Практические рекомендации:
- Избегайте дефолтного конструктора, если заранее известен примерный размер коллекции. Указание начальной ёмкости предотвращает многократные дорогостоящие операции копирования массива при росте.
size()vscapacity():size()возвращает количество элементов в списке, аcapacity()— длину внутреннего массива (этот метод private, но его логику можно понять).
Ответ 18+ 🔞
А, слушай, смотри, тут народ часто путается, как там этот ArrayList внутри устроен, особенно про начальный размер. Ну, типа, все помнят, что там десятка, да? А вот хуй там, с восьмой Java всё поменялось, блядь!
Вот представь: ты создаёшь список через new ArrayList<>(). И думаешь: "Ну всё, там внутри массив на 10 ячеек уже лежит, готовый". А нихуя подобного, ёпта! На самом деле, внутри сейчас ноль, полный ноль! Массив-то создаётся лениво, как последняя мартышка, только когда ты первый элемент сунешь. До этого там пустая заглушка торчит.
Как это работает, блядь:
- Создал список — получил пшик. Конструктор без параметров просто тычет ссылку на пустую константу. Никакого массива ещё нет, ядрёна вошь!
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // По сути, просто {} } - Первый
add()— и понеслась. Ты добавляешь первый элемент, и код такой: "О, так тут же пустышка! Ладно, создаём нормальный массив". И создаёт его размеромDEFAULT_CAPACITY, а это как раз та самая десятка. - Дальше — по накатанной. Массив заполнился? Щас мы его расширим! Берут старый размер, сдвигают вправо (это деление на два, но типа быстро), и прибавляют. Получается примерно в полтора раза больше. Старый массив — нахуй, новый — красава, всё туда копируется.
А если ты не лох и размер примерно знаешь? То есть конструкторы, где можно не ждать милости от JVM:
// Сразу говоришь: дай мне массив на 20, чтобы не дергался потом
ArrayList<String> listWithCapacity = new ArrayList<>(20);
// Или скопировал из другой коллекции — размер подстроится
ArrayList<String> listFromCollection = new ArrayList<>(someOtherList);
Вывод, чтобы не быть мудаком:
- Не используй дефолтный конструктор просто так, если знаешь, сколько примерно элементов будет. Сказал размер заранее — избежал кучи лишних копирований массива, когда он будет расти. Это ж операция не из лёгких, блядь!
- И запомни разницу, а то опозоришься:
size()— это сколько элементов ты уже засунул, а ёмкость (capacity) — это сколько всего можно засунуть прямо сейчас, пока массив снова не порвётся. Только вот capacity — штука приватная, наружу не торчит, но логику-то понимать надо, а то как жить?