JavaRush /Курсы /Java Syntax Pro /Работа с ArrayList

Работа с ArrayList

Java Syntax Pro
12 уровень , 3 лекция
Открыта

1. Как устроен ArrayList

ArrayList — самый распространённый класс в Java для хранения элементов. Так как же устроен этот ArrayList и почему он так всем нравится?

Устройство ArrayList простое и гениальное по своей сути. Внутри каждого объекта ArrayList есть два поля:

  • Массив со списком элементов
  • Переменная size, которая хранит количество элементов списка

Внутри объекта ArrayList содержится самый обычный массив! Но не только. Там есть еще переменная size, которая хранит длину списка. Вот как это работает:

Изначально длина массива внутри списка — 10 элементов. А переменная size равна 0.

Если в список добавить элемент, он будет сохранен в 0-ю ячейку массива, а size увеличится до 1.

Если добавить еще один элемент, он будет сохранен в 1-ю ячейку, а size снова увеличится на 1 и теперь будет равняться двум.

Если при добавлении очередного элемента в список в массиве уже нет места, в методе add() происходит следующее:

  1. создается новый массив в полтора раза длиннее предыдущего
  2. в него копируются все элементы из существующего массива
  3. в объекте ArrayList вместо старого массива сохраняется ссылка на новый.
  4. В 10-ю ячейку нового массива записывается переданный элемент
  5. size увеличивается на 1 и теперь будет равняться 11

Аналогично при добавлении (вставке) элемента в середину списка. Существующие элементы сдвигаются на 1 вправо, и в свободную ячейку массива записывается нужный элемент.

Самые основные сценарии использования списка мы сейчас рассмотрим:


2. Добавление элемента в ArrayList

Давайте разберём, что происходит внутри списка, когда в него добавляются элементы. Сразу после создания объекта ArrayList мы имеем в памяти примерно такую картину:

Добавление элемента в ArrayList

У нас есть объект типа ArrayList, внутри которого два поля (две переменные): массив (data) и количество элементов (size). data хранит ссылку на контейнер (массив) из 10 элементов.

Если мы решим добавить в массив число 5, получится такая картина:

Добавление элемента в ArrayList

В массиве теперь хранится элемент 5, а переменная size == 1.

Если сейчас кто-то вызовет метод size() у нашего объекта ArrayList, он получит количество элементов списка — 1. Количество элементов списка — это не размер массива.

Ни действительный размер массива, ни сам массив никогда не будут доступны (видны) вне объекта ArrayList. Это внутренние данные ArrayList, и они всегда ими останутся.

Давайте добавим в список еще 7 чисел: 10, 20, 30, 40, 50, 60, 70.

Тогда картина в памяти будет уже такой:

Добавление элемента в ArrayList 2

Если сейчас вызвать метод size(), он вернет число 8 — новое количество элементов в списке. К размеру массива оно не имеет никакого отношения.

Важно:

На этой картинке есть одна неточность.

Класс ArrayList не может хранить примитивные типы, поэтому вместо типа int он использует тип Integer. Контейнер хранит не значения 5-70, а ссылки на объекты типа Integer. Все пустые ячейки контейнера хранят null.



3. Увеличение длины списка

Давайте разберем, что происходит внутри списка, когда в его массиве заканчиваются свободные ячейки.

Допустим, у нас был список из 10 элементов:

Увеличение длинны списка

Мы решили добавить в него число 100, вот что при этом произойдет в методе add() :

Шаг 1 — создание нового массива:

Увеличение длинны списка 1

Шаг 2 — копирование всех элементов из старого массива в новый:

Увеличение длинны списка

Шаг 3 — замена массива (изменение ссылки на массив внутри объекта ArrayList):

Увеличение длинны списка 3

Шаг 4 — добавление нового числа, ради чего мы так старались:

Увеличение длинны списка 4

Комментарии (309)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Grigoryvvv Уровень 13 Expert
14 января 2026
14.01.2026 / 13 уровень
Georgii Serdiukov Уровень 15
8 октября 2025
Когда будете менять длину массива, вам нужно будет умножить в полтора раза. Скорее всего, вы будете делать это с помощью Math. Нужно брать округление вниз, а не вверх, что логично, но я здесь затупил немного
Denis Pereladov Уровень 22
15 декабря 2025
Тут достаточно приведения к (int), оно отбрасывает дробную часть, что эквивалентно округлению вниз.
20 августа 2025
Я долго ломал голову над тем, почему предыдущий материал противоречит этой лекции, а точнее неизменность массива, ранее говорили, что его менять нельзя, а в задаче хотят чтобы мы поменяли массив, но потом с помощью chatGPT разобрался. Будущие коллеги(те кто не понял), в этой лекции рассказывается как устроен ArrayList под капотом. Решив задачу самостоятельно, вы сможете сами создавать свою реализацию ArrayList, хотя пока что не знаю нужно будет это делать или нет. Удачи вам, не сдавайтесь, жду вас где-то далеко впереди :D
Руслан Уровень 48
28 июля 2025
Очень интересная лекция!!!
Anonymous #3585174 Уровень 33
29 июня 2025
like
Виктор Уровень 24
1 июня 2025
После 4 дней отдыха сложновато втягиваться заного) прям мозг прикипает. Начинаю с легких лекций на ютуб фоном, потом читаю разок быстро тему даже если не понимаю. А после уже вчитываюсь для понимания, решаю задачи и процесс пошел.
Anonistus #3456 Уровень 14
29 мая 2025
Просто хочу сказать, что писанина (статьи) джава раш мною плохо перевариваются и много чего не понятно, а вот после просмотра роликов не ютубчике где объясняется та же тема - все становится предельно ясно.
Georgy Dmitriev Уровень 19
27 июля 2025
как итог ты решаешь задачу и забываешь а когда через время вновь сталкиваешься с похожим колесо сансары дает оборот и ты снова идешь в ютубчик чтобы посмотреть тот же видос - вывод видеоинформация абсолютно не укладывается в голове
Юрий Болотин Уровень 16
20 апреля 2025
Всем привет! До JDK 6 пропускная способность (capacity grow) увеличивается с помощью формулы:

newCapacity = (oldCapacity * 3)/2 + 1 = 16.
. В JDK 7 и выше формула меняется на

newCapacity = oldCapacity + (oldCapacity >> 1)
. >> 1 - сдвиг на один разряд вправо, который даст 00000101, что в десятичной системе равно 5, поэтому newCapacity равно 10 + 5 = 15. Таким образом, если начальная мощность равна 10, то новая мощность (capacity) будет 16 in JDK6 и 15 in above JDK7. Также прочитал, что есть глубокое (deep) и поверхностное (shallow) копирование.
14 мая 2025
capacity = capacity*1/2+capacity; так нельзя? тоесть если capacity = 10 ==> capacity = 10*1/2+10
Vladislav Terekh Уровень 34
16 мая 2025
Можно и ещё проще.

сapacity += сapacity / 2;
И прочитает любой, и преобразования в int не понадобятся. А вот зачем в примере выше с JDK 6 мы увеличиваем capacity до 16-ти, а не до 15-ти, при чем делаем это собственноручно, добавляя лишнюю единицу - мне вообще не понятно.
MaestroVLG Уровень 17
18 апреля 2025
год изучения программирования, сначала питон(с апреля по февраль), теперь джава. итог - программистами могут быть вообще не все, всем спасибо
19 апреля 2025
+ + даже человек начавший с питона, смог одуматься и перейти на джава =)
Сергей Сак Уровень 16
17 мая 2025
Ну вообще Java - сложный язык программирования для старта. Раньше нас в школе обучали паскалю (а не джава), что давало нам представление о программировании. Сейчас обучаются пайтону, так как это очень легкий язык программирования для старта
Сергей Сак Уровень 16
16 апреля 2025

Изначально длина массива внутри списка — 10 элементов.
Открываем класс ArrayList и видим:

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/*
*/
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
Что говорит нам о том, что изначально длина массива внутри списка - 0 элементов. При добавлении элемента в массив (метод add) будет выполняться проверка и, когда выяснится, что массив имеет размер 0 элементов, будет создан новый массив, где уже как-раз будет использоваться размер по умолчанию в 10 элементов.

return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)]; 
// тут minCapacity - это значение size + 1