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

Работа с ArrayList

Открыта

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

Комментарии (306)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Euraks Backend Developer
28 сентября, 17:30
В ArrayList используется System.arraycopy что делает его быстрее List на практике, но не теоретически. Хотя на больших объемах и теоретически ArrayList быстрее List. Но тема это сложная надо шарить. и если разберетесь на собесе можно похоливарить ))
Анна Sowa
Уровень 26
21 сентября, 17:51
Кто начинающий, посмотрите в папку с этой задачей (task1212) в IDE, там найдете сам класс CustomStringArrayList со всем его содержимым. Задача сразу станет понятнее.
Grigoryvvv
Уровень 28
Expert
14 января, 11:36
14.01.2026 / 13 уровень
Georgii Serdiukov
Уровень 15
8 октября 2025, 21:12
Когда будете менять длину массива, вам нужно будет умножить в полтора раза. Скорее всего, вы будете делать это с помощью Math. Нужно брать округление вниз, а не вверх, что логично, но я здесь затупил немного
Denis Pereladov
Уровень 40
15 декабря 2025, 05:50
Тут достаточно приведения к (int), оно отбрасывает дробную часть, что эквивалентно округлению вниз.
20 августа 2025, 15:59
Я долго ломал голову над тем, почему предыдущий материал противоречит этой лекции, а точнее неизменность массива, ранее говорили, что его менять нельзя, а в задаче хотят чтобы мы поменяли массив, но потом с помощью chatGPT разобрался. Будущие коллеги(те кто не понял), в этой лекции рассказывается как устроен ArrayList под капотом. Решив задачу самостоятельно, вы сможете сами создавать свою реализацию ArrayList, хотя пока что не знаю нужно будет это делать или нет. Удачи вам, не сдавайтесь, жду вас где-то далеко впереди :D
Руслан
Уровень 48
28 июля 2025, 09:39
Очень интересная лекция!!!
Anonymous #3585174
Уровень 33
29 июня 2025, 12:59
like
Виктор
Уровень 28
1 июня 2025, 10:06
После 4 дней отдыха сложновато втягиваться заного) прям мозг прикипает. Начинаю с легких лекций на ютуб фоном, потом читаю разок быстро тему даже если не понимаю. А после уже вчитываюсь для понимания, решаю задачи и процесс пошел.
Anonistus #3456рукоблуд в швейный цех
29 мая 2025, 11:53
Просто хочу сказать, что писанина (статьи) джава раш мною плохо перевариваются и много чего не понятно, а вот после просмотра роликов не ютубчике где объясняется та же тема - все становится предельно ясно.
GeorgyIngineer в void
27 июля 2025, 07:26
как итог ты решаешь задачу и забываешь а когда через время вновь сталкиваешься с похожим колесо сансары дает оборот и ты снова идешь в ютубчик чтобы посмотреть тот же видос - вывод видеоинформация абсолютно не укладывается в голове
Юрий Болотин
Уровень 11
20 апреля 2025, 17:25
Всем привет! До 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, 10:21
capacity = capacity*1/2+capacity; так нельзя? тоесть если capacity = 10 ==> capacity = 10*1/2+10
Vladislav Terekh
Уровень 34
16 мая 2025, 18:47
Можно и ещё проще.
сapacity += сapacity / 2;
И прочитает любой, и преобразования в int не понадобятся. А вот зачем в примере выше с JDK 6 мы увеличиваем capacity до 16-ти, а не до 15-ти, при чем делаем это собственноручно, добавляя лишнюю единицу - мне вообще не понятно.