JavaRush /Курси /Java Syntax Zero /Робота з ArrayList

Робота з ArrayList

Java Syntax Zero
Рівень 13 , Лекція 4
Відкрита

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

Коментарі (8)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Christopher Ward 595 Рівень 16
6 серпня 2024
Трошки скучно було через for вирішувати задачу, тому знайшов System.arraycopy(Object src, int srcIndex, Object dest, int destIndex, int length), де 1)src: Масив який копіюєм. 2)srcIndex: індекс з якого копіюємо в вихідному масиві 3)dest: Масив в який вставляємо 4)destIndex: індекс з якого вставляємо в новий масиві 5)length: кількість елементів які ми хочемо скопіювати в вихідному масиві.
Гаркін Рівень 14
21 травня 2024
А в завданні "Створюємо свій список" arrayList в нас вийшов хитрозробленою тваринкою, яка не є масивом (arrayList.length не спрацює, як і Arrays.toString(arrayList) ), і яка не є колекцією (тобто arrayList.size() також не спрацює). Ну і як дізнатись її розмір? (створити геттер для size. А ще геттер для capacity - цікаве число побачите.)
Natalya Рівень 20
25 жовтня 2024
Можна розмір виразити через capacity не використовуючи геттер
Пузирєй Денис Рівень 28
26 жовтня 2023
Цей Array.List, справді класна штука. Все настільки продумано. Круто
Yaroslav Tkachyk Рівень 23 Expert
6 січня 2023
Ще питання: "Створюється новий масив, у півтора раза довший за попередній." © В статтях описаний розмір нового внутрішнього масиву = (розмірСтарогоМасиву * 1.5) + 1 Де правда? :)
Roma Chernesh Рівень 16
22 січня 2023
Ото просто заплутано написано. Розмір нового масиву = (розмірСтарогоМасиву * 1.5) І це все. А про додавання + 1. Це вже йшлося про лічильник елементів у масиві. *тобто в нас є окремо "розмір масива" і "кількість елементів". Якщо цей момент незрозумілий, треба перечитати попередню статтю. По суті, ось усе, що пов'язано із розміром нового масиву (коли у старому закінчилося місце): Якщо при спробі додавання чергового елемента до списку в масиві вже немає місця, у методі add() відбувається от що: Створюється новий масив, у півтора раза довший за попередній ВСЕ
Yaroslav Tkachyk Рівень 23 Expert
4 січня 2023
Привіт! "В 11-ту комірку нового масиву записується переданий елемент..." © Питання: чому в 11-ту, а не в 10-ту? Був масив на 10 елементів з комірками 0,1,2,3,4,5,6,7,8,9 - які всі вже заповнені елементами; Створюється масив на 15 елементів з комірками 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14; Елементи зі старого масиву копіюються в новий масив; При додаванні наступного елементу - наступна вільна комірка (зі значенням за замовчуванням null) - це десята комірка в яку додається 11 елемент.
theylovevalera Рівень 51
22 лютого 2023
В лекції йдеться про порядок комірки у людському розумінні(відліку від 1),а не компіляторовому.11 комірка-це 11 комірка для нас,а для компілятора-вона 10)