1. Клас ArrayList
У Java інтерфейс List — це контракт: «Я — впорядкована колекція елементів, з якої можна отримати елемент за номером (індексом)».
Ключові властивості списку (List):
- Елементи зберігаються у певному порядку (на відміну від множини).
- Можна зберігати дублікати елементів (наприклад: двічі "Андрій").
- Можна звернутися до елемента за індексом: перший елемент — індекс 0, другий — 1 і так далі.
- Можна додавати й видаляти елементи в будь-яке місце списку.
Найпопулярніша реалізація інтерфейсу List — це ArrayList. Усередині він використовує звичайний масив і автоматично збільшує розмір зі зростанням даних.
Як створити ArrayList?
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
// Створюємо список рядків
List<String> students = new ArrayList<>();
}
}
Пояснення
- List<String> — це змінна типу «список рядків». Змінну оголошуємо за інтерфейсом, а об’єкт створюємо конкретним класом (ArrayList).
- Кутові дужки <String> задають тип елементів списку — дженерики (generics).
Основні методи ArrayList (і взагалі будь-якого List):
- add(element) — додати елемент у кінець списку.
- add(index, element) — вставити елемент за конкретним індексом.
- get(index) — отримати елемент за індексом.
- set(index, element) — замінити елемент за індексом.
- remove(index) — видалити елемент за індексом.
- remove(Object) — видалити перший знайдений елемент, що дорівнює переданому об’єкту.
- size() — дізнатися кількість елементів у списку.
Приклад: Працюємо зі списком студентів
import java.util.ArrayList;
import java.util.List;
public class StudentListDemo {
public static void main(String[] args) {
List<String> students = new ArrayList<>();
// Додаємо студентів
students.add("Андрій");
students.add("Петро");
students.add("Марія");
// Виводимо всіх студентів
System.out.println("Список студентів: " + students);
// Отримуємо першого студента
String first = students.get(0);
System.out.println("Перший студент: " + first);
// Змінюємо імʼя другого студента
students.set(1, "Павло");
System.out.println("Після зміни: " + students);
// Видаляємо Марію
students.remove("Марія");
System.out.println("Після видалення Марії: " + students);
// Розмір списку
System.out.println("Усього студентів: " + students.size());
}
}
Результат:
Список студентів: [Андрій, Петро, Марія]
Перший студент: Андрій
Після зміни: [Андрій, Павло, Марія]
Після видалення Марії: [Андрій, Павло]
Усього студентів: 2
Як це пов’язано з вашим застосунком?
Припустімо, що у вас є застосунок для обліку студентських завдань. Ви можете зберігати список завдань як List<String>, а не як масив, і динамічно додавати нові записи.
2. Клас LinkedList: коли важлива швидкість вставлення та видалення
LinkedList — альтернативна реалізація списку. Влаштований як двозвʼязний ланцюжок: кожен вузол знає попередній і наступний елементи. Як у складі потяга: вставити «вагон» посередині можна швидко й без перебудови всього складу.
Створення LinkedList
import java.util.LinkedList;
import java.util.List;
public class Example {
public static void main(String[] args) {
List<String> tasks = new LinkedList<>();
}
}
Особливості LinkedList
- Швидке вставлення та видалення на початку й у середині списку.
- Повільний доступ за індексом (щоб знайти 100-й елемент, потрібно пройтися ланцюжком).
- Підходить, якщо ви часто додаєте або видаляєте елементи не лише в кінець, а й на початок чи в середину.
Приклад: Використовуємо LinkedList
import java.util.LinkedList;
import java.util.List;
public class TaskListDemo {
public static void main(String[] args) {
List<String> tasks = new LinkedList<>();
tasks.add("Прокинутися");
tasks.add("Поснідати");
tasks.add("Піти на пари");
// Додаємо завдання на початок
tasks.add(0, "Поставити будильник");
System.out.println("Список завдань: " + tasks);
// Видаляємо перше завдання (найраніше)
tasks.remove(0);
System.out.println("Після видалення першого завдання: " + tasks);
}
}
3. Порівняння ArrayList і LinkedList
| Критерій | |
|
|---|---|---|
| Основа | Масив | Двозвʼязний список |
| Швидкий доступ за індексом | Так (O(1)) | Ні (O(n)) |
| Швидке вставлення/видалення на початку/у середині | Ні (O(n)) | Так (O(1) — якщо є посилання) |
| Швидке вставлення/видалення в кінці | Так (зазвичай O(1)) | Так (O(1)) |
| Памʼять | Споживає менше памʼяті | Більше (через додаткові посилання на сусідів) |
| Типові завдання | Частий доступ за індексом | Часті вставлення/видалення |
Просте правило:
- Потрібен швидкий доступ за індексом — використовуйте ArrayList.
- Часто додаєте або видаляєте на початку чи в середині — використовуйте LinkedList.
4. Типові операції зі списками
Перебирання елементів списку
Звичайний цикл for
for (int i = 0; i < students.size(); i++) {
System.out.println("Студент №" + i + ": " + students.get(i));
}
Цикл for-each (найпопулярніший спосіб)
for (String name : students) {
System.out.println("Імʼя: " + name);
}
Лямбда-вираз (Java 8+)
students.forEach(name -> System.out.println("Імʼя: " + name));
Пошук елементів
- contains(element) — повертає true, якщо елемент є у списку.
- indexOf(element) — повертає індекс першого входження елемента або -1, якщо не знайдено.
if (students.contains("Андрій")) {
System.out.println("Андрій є у списку!");
}
int index = students.indexOf("Андрій");
System.out.println("Індекс Андрія: " + index);
Очищення списку
clear() — видаляє всі елементи.
students.clear();
System.out.println("Список після очищення: " + students);
5. Коли використовувати ArrayList, а коли LinkedList?
Зручно мислити так: ArrayList доречний там, де потрібно швидко звертатися до елементів за індексом і список змінюється нечасто. Наприклад, великий список користувачів або історія повідомлень — переважно читання.
LinkedList, навпаки, корисний, коли постійно вставляєте або видаляєте елементи на початку чи у середині. Це може бути черга, стек або історія скасування дій.
На практиці найчастіше використовують ArrayList, а LinkedList радше інструмент «на всяк випадок»: лежить у шухляді, але іноді саме він і потрібен.
6. Типові помилки під час роботи зі списками
Помилка № 1: Вихід за межі списку. Найпоширеніша ситуація — звернення за неіснуючим індексом. Якщо список із трьох елементів, а ви пишете students.get(5), отримаєте IndexOutOfBoundsException. Перед доступом перевіряйте size().
Помилка № 2: Видалення елемента під час перебору. Під час перебору через for-each і одночасного видалення елементів виникне ConcurrentModificationException. Для складних видалень використовуйте цикл за індексом або Iterator.
Помилка № 3: Неправильне порівняння об’єктів. Якщо ви зберігаєте власні об’єкти (наприклад, Student), методи contains і remove спираються на equals. Якщо його не перевизначити, порівняння буде за посиланням, а не за вмістом.
Помилка № 4: Використання сирих типів. Не пишіть List list = new ArrayList() — завжди вказуйте тип елементів: List<String> list = new ArrayList<>(). Дженерики захищають від помилок і роблять код зрозумілішим.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ