Java Collections Framework: List, Set чи Map?

Уявіть, що ви прийшли на склад інтернет-магазину. На одній полиці товари лежать строго в тому порядку, у якому їх привезли. На іншій — кожен предмет унікальний, і дублікати сюди не кладуть за жодних умов. А в кутку стоїть картотека, де кожному товару відповідає унікальний штрих-код.

У світі Java цей склад називається Java Collections Framework (JCF). Це потужний набір інтерфейсів та класів, який дозволяє ефективно керувати групами об’єктів. Проте у початківців часто виникає питання: яку саме структуру даних обрати для вирішення конкретного завдання?

Давайте розберемося з «великою трійкою» JCF — ListSet та Map — раз і назавжди.


1. List (Список): Коли важливий порядок та індекси

List — це впорядкована колекція, елементи якої зберігаються у тій послідовності, у якій ви їх туди додали. Кожен елемент має свій індекс (починаючи з 0), що дозволяє миттєво дістати його за цим номером.

  • Особливості: Дозволяє зберігати дублікати (однакові значення) та значення null.
  • Найпопулярніші реалізації:
    • ArrayList: В основі лежить динамічний масив. Ідеально підходить для швидкого доступу до елементів за індексом (O(1)). Проте видалення чи додавання елементів у середину списку працює повільно, бо доводиться зсувати інші елементи.
    • LinkedList: Двозв’язний список, де кожен елемент знає про свого сусіда. Швидко додає та видаляє елементи з початку чи кінця (O(1)), але пошук за індексом вимагає проходу по всьому ланцюжку.
  • Коли обирати? Коли вам потрібна стрічка новин, історія повідомлень у чаті, кошик покупок або будь-яка черга, де порядок додавання має першочергове значення.

Життєвий приклад: Список студентів у журналі викладача. Черговість важлива (наприклад, за списком), і цілком можлива ситуація, коли у групі є два студенти з абсолютно однаковими іменами та прізвищами (дублікати).

import java.util.ArrayList;
import java.util.List;

public class ListExample {
    public static void main(String[] args) {
        // Створюємо список студентів
        List<String> students = new ArrayList<>();

        // Додаємо елементи (порядок збережеться)
        students.add("Олексій");
        students.add("Марія");
        students.add("Іван");
        students.add("Марія"); // Дозволено дублікат!

        // Доступ за індексом (швидко)
        String firstStudent = students.get(0); 
        System.out.println("Перший у списку: " + firstStudent); // Олексій

        // Виводимо весь список
        System.out.println("Весь список студентів: " + students);
        // Результат: [Олексій, Марія, Іван, Марія]
    }
}
Java

2. Set (Множина): Боротьба з дублікатами

Set — це колекція, яка моделює математичну множину. Її головне правило: ніяких дублікатів. Якщо ви спробуєте додати елемент, який вже є у множині, колекція просто проігнорує цю дію.

  • Особливості: У більшості реалізацій порядок елементів не гарантується.
  • Найпопулярніші реалізації:
    • HashSet: Базується на хеш-таблиці. Забезпечує надзвичайно швидкий пошук, додавання та видалення елементів за константний час (O(1)). Але порядок зберігання хаотичний.
    • LinkedHashSet: Працює майже як HashSet, але запам’ятовує порядок додавання елементів.
    • TreeSet: Зберігає елементи у відсортованому порядку (за зростанням або за допомогою вашого власного правила Comparator). Працює трохи повільніше за HashSet через необхідність балансування дерева.
  • Коли обирати? Коли потрібно зберігати унікальні дані: список ID користувачів, унікальні IP-адреси відвідувачів сайту, або теги для статті.

Життєвий приклад: Набір тегів під статтею. Немає сенсу писати тег #java двічі під одним постом. Система повинна автоматично відсікати дублікати.

import java.util.HashSet;
import java.util.Set;

public class SetExample {
    public static void main(String[] args) {
        // Створюємо множину тегів
        Set<String> tags = new HashSet<>();

        // Додаємо теги
        tags.add("java");
        tags.add("spring");
        tags.add("programming");
        tags.add("java"); // Спроба додати дублікат

        // Перевіряємо розмір та вміст
        System.out.println("Кількість тегів: " + tags.size()); // Виведе 3, а не 4!
        System.out.println("Унікальні теги: " + tags);
        // Порядок виведення може бути випадковим: [programming, java, spring]
        
        // Швидка перевірка наявності елемента
        if (tags.contains("spring")) {
            System.out.println("Тег 'spring' знайдено!");
        }
    }
}
Java

3. Map (Карта/Словник): Парами «Ключ — Значення»

Важливо зазначити: хоча Map є частиною фреймворку колекцій Java, цей інтерфейс не успадковується від базового інтерфейсу Collection. Проте концептуально це одна з найважливіших структур. Вона зберігає дані парами: унікальний Ключ та асоційоване з ним Значення.

  • Особливості: Ключі мають бути унікальними, тоді як значення можуть дублюватися.
  • Найпопулярніші реалізації:
    • HashMap: Швидкий доступ до значень за ключем (O(1)). Порядок пар не гарантований.
    • LinkedHashMap: Зберігає порядок додавання елементів за ключами.
    • TreeMap: Сортує пари за ключами.
  • Коли обирати? Коли потрібно зв’язати дані між собою: телефонна книга (ім’я -> номер), паспортні дані (номер паспорта -> дані людини), або словник (слово -> його переклад).

Життєвий приклад: Кошик в інтернет-магазині. Ключем є унікальний артикул товару (ID), а значенням — кількість штук, яку користувач хоче придбати.

import java.util.HashMap;
import java.util.Map;

public class MapExample {
    public static void main(String[] args) {
        // Створюємо карту (Ключ - ID товару (Integer), Значення - Кількість (Integer))
        Map<Integer, Integer> cart = new HashMap<>();

        // Додаємо товари до кошика
        cart.put(101, 1); // Товар з ID 101 у кількості 1 шт.
        cart.put(102, 3); // Товар з ID 102 у кількості 3 шт.
        
        // Оновлюємо значення для існуючого ключа (перезапис)
        cart.put(101, 2); // Тепер товару 101 стало 2 шт.

        // Отримуємо значення за ключем
        int countOfItem102 = cart.get(102);
        System.out.println("Кількість товару 102 у кошику: " + countOfItem102); // 3

        // Прохід по всій карті (Key-Value)
        for (Map.Entry<Integer, Integer> entry : cart.entrySet()) {
            System.out.println("Товар ID: " + entry.getKey() + " | Кількість: " + entry.getValue());
        }
    }
}
Java

Шпаргалка для вибору: Золоті правила розробника

Щоб не помилитися під час написання коду, ставте собі три прості запитання:

  1. Чи потрібні мені пари “ключ-значення”? Якщо так — ваш вибір Map (частіше за все HashMap).
  2. Чи мають дані бути унікальними? Якщо дублікати неприпустимі — використовуйте Set (зазвичай HashSet).
  3. Чи важливий мені порядок додавання або доступ за номером? Якщо так — обирайте List (найчастіше ArrayList).

Опанування цих трьох концепцій — це фундамент, на якому будується вся бізнес-логіка сучасних Java-додатків. Пишіть код усвідомлено, обирайте правильні інструменти під ваші завдання, і ваші програми працюватимуть швидко та ефективно!


Зведена порівняльна таблиця для закріплення

Критерій List (ArrayList)Set (HashSet)Map (HashMap)

Формат збереження
Поодинокі об’єктиПоодинокі об’єктиПари “Ключ-Значення”

Допуск дублікатів
Так, дозволеноНі, тільки унікальніКлючі — унікальні, Значення — ні
Порядок елементів
Зберігається (за індексами)
Переважно хаотичний
Переважно хаотичний

Головна перевага

Швидкий доступ за номеромМоментальна фільтрація дублікатівШвидкий пошук значення за його ключем

Коли ви обираєте інтерфейс ListSet або Map — це лише половина справи. Справжня магія (і головні підводні камені продуктивності) криється в конкретних реалізаціях. Чому ArrayList іноді гальмує? Навіщо потрібен TreeSet, якщо є швидкий HashSet? І коли TreeMap стає незамінним?

Давайте розберемо шість найпопулярніших реалізацій Java Collections Framework на простих життєвих аналогіях та зрозумілих прикладах коду.

1. List: ArrayList проти LinkedList

ArrayList: Динамічний масив (Швидкий доступ)

  • Аналогія: Ряд крісел у кінотеатрі. Кожне крісло має чіткий номер. Ви можете миттєво сісти на крісло №5, але якщо захочете вставити нове крісло посередині ряду, усім глядачам праворуч доведеться підвестися й пересісти на одне місце далі.
  • Особливості: Швидкий пошук за індексом, але повільне додавання/видалення елементів всередині списку.
  • Приклад використання: Список користувачів у системі, який ми часто читаємо і рідко змінюємо.

LinkedList: Двозв’язний список (Швидкі зміни)

  • Аналогія: Діти, які тримаються за руки під час прогулянки. Кожна дитина знає лише того, хто стоїть попереду, і того, хто позаду. Щоб вставити нову дитину всередину, достатньо розімкнути одну пару рук і перехопити сусідів. Але щоб знайти 10-ту дитину, вам доведеться рахувати з самого початку.
  • Особливості: Швидке додавання та видалення елементів на початку та в кінці, але повільний пошук за індексом.
  • Приклад використання: Черга завдань на друк у принтері.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ListsComparison {
    public static void main(String[] args) {
        // ArrayList: ідеально для читання
        List<String> movieSeats = new ArrayList<>();
        movieSeats.add("Крісло 1");
        movieSeats.add("Крісло 2");
        System.out.println("Швидкий доступ за індексом: " + movieSeats.get(1)); // Крісло 2

        // LinkedList: ідеально для динамічних черг
        List<String> printQueue = new LinkedList<>();
        printQueue.add("Документ_1.pdf");
        printQueue.add("Фото.png");
        printQueue.add(0, "Терміновий_Договір.pdf"); // Швидка вставка на початок!
        System.out.println("Черга друку: " + printQueue);
    }
}
Java

2. Set: HashSet проти TreeSet

HashSet: Швидкість та хаос

  • Аналогія: Коробка з унікальними деталями LEGO. Ви можете дуже швидко засунути туди руку і перевірити, чи є там червоний кубик (завдяки магічній математиці хеш-кодів). Але деталі всередині лежать у повному безладі.
  • Особливості: Найвища швидкість роботи (O(1)), порядок елементів випадковий.
  • Приклад використання: Список унікальних IP-адрес, що відвідали сайт за день.

TreeSet: Ідеальний порядок

  • Аналогія: Словник на полиці. Усі слова унікальні та автоматично відсортовані за алфавітом (або числа за зростанням). Шукати слово трохи довше, ніж у коробці, але ви завжди знаєте, що йде після чого.
  • Особливості: Працює повільніше за HashSet (O(log n)), але автоматично сортує всі елементи.
  • Приклад використання: Таблиця лідерів у грі (усі нікнейми унікальні та відсортовані за рейтингом).
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public class SetsComparison {
    public static void main(String[] args) {
        // HashSet: швидкість без гарантії порядку
        Set<String> hashSet = new HashSet<>();
        hashSet.add("Яблуко");
        hashSet.add("Банан");
        hashSet.add("Апельсин");
        System.out.println("HashSet (порядок випадковий): " + hashSet); 
        // Результат може бути: [Банан, Апельсин, Яблуко]

        // TreeSet: автоматичне сортування за алфавітом
        Set<String> treeSet = new TreeSet<>();
        treeSet.add("Яблуко");
        treeSet.add("Банан");
        treeSet.add("Апельсин");
        System.out.println("TreeSet (відсортовано): " + treeSet); 
        // Результат ЗАВЖДИ: [Апельсин, Банан, Яблук��]
    }
}
Java

3. Maps(Словники): HashMap проти TreeMap

HashMap: Швидкий словник

  • Аналогія: Вішалка в гардеробі театру. Ви даєте номерний жетон (ключ) — вам миттєво видають вашу куртку (значення). Номери жетонів не обов’язково йдуть підряд на вішалці, але обмін відбувається миттєво.
  • Особливості: Миттєвий доступ до значень за ключем. Порядок ключів не зберігається.
  • Приклад використання: База користувачів, де ключ — унікальний user_id, а значення — об’єкт User.

TreeMap: Сортування за ключами

  • Аналогія: Реєстраційна книга в архіві. Кожен запис має унікальний номер (ключ) і опис справи (значення). Усі записи впорядковані строго за зростанням номерів справ, що дозволяє швидко виводити звіти за діапазонами номерів.
  • Особливості: Повільніший за HashMap, але гарантує сортування даних за ключами.
  • Приклад використання: Звітність компанії, де ключ — дата транзакції, а значення — сума (дозволяє легко отримати транзакції “від дати Х до дати Y”).
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class MapsComparison {
    public static void main(String[] args) {
        // HashMap: швидкість понад усе
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(50, "Офіс на 5 поверсі");
        hashMap.put(10, "Ресепшн");
        hashMap.put(30, "Кафетерій");
        System.out.println("HashMap (порядок хаотичний): " + hashMap);

        // TreeMap: ключі автоматично сортуються (10, 30, 50)
        Map<Integer, String> treeMap = new TreeMap<>();
        treeMap.put(50, "Офіс на 5 поверсі");
        treeMap.put(10, "Ресепшн");
        treeMap.put(30, "Кафетерій");
        System.out.println("TreeMap (відсортовано за ключем): " + treeMap);
        // Результат: {10=Ресепшн, 30=Кафетерій, 50=Офіс на 5 поверсі}
    }
}
Java

Підсумкова таблиця для порівняння

РеалізаціяПід капотомШвидкість пошукуЧи сортує елементи?Коли обирати?
ArrayListДинамічний масив⚡ Дуже швидко за індексом O(1)НіПотрібно часто читати дані
LinkedListДвозв’язний список🐢 Повільно (потрібен перебір)НіЧасте додавання/видалення в кінці чи на початку
HashSetХеш-таблиця⚡ Надзвичайно швидко O(1)НіПотрібна максимальна швидкість та унікальність
TreeSetЧервоно-чорне дерево⚖️ Середня O(log n)Так, за значеннямПотрібен унікальний відсортований список
HashMapХеш-таблиця⚡ Надзвичайно швидко O(1)НіПотрібно швидко шукати значення за унікальним ключем
TreeMapЧервоно-чорне дерево⚖️ Середня O(log n)Так, за ключемПотрібно зберігати пари та мати сортування за ключами

javaadmin

Супер крутий Dev

Related Posts

Міграція Java-додатків на Spring Boot 3: Spring Boot Properties Migrator

Перехід на Spring Boot 3 є значним кроком для будь-якого Java-додатку, оскільки ця версія вносить багато змін, включаючи перехід на Jakarta, оновлення залежностей та зміни в конфігурації. Одним із найкорисніших інструментів для полегшення цього процесу є Spring Boot Properties Migrator — компонент, який автоматично допомагає виявляти застарілі налаштування та пропонує їх сучасні альтернативи. Що таке Spring Boot Properties Migrator? Spring Boot Properties Migrator — це спеціальна бібліотека, яка…

Stream API в Java: Потужні рішення які покращать ваш код

Stream API з’явився в Java 8 і докорінно змінив підхід до обробки колекцій. Якщо ви досі пишете вкладені цикли для фільтрації та трансформації даних, ця стаття для вас. Розглянемо 5 практичних прикладів, які покажуть всю потужність Stream API. 1. Фільтрація та трансформація в один рядок Завдання: Отримати список email-адрес активних користувачів, відсортованих за алфавітом. Традиційний підхід: З Stream API: Код став коротшим, читабельнішим і декларативним. Ми описуємо “що”…

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Цікаве

Dependency Injection у Spring: пояснюємо на пальцях

  • Автор javaadmin
  • 31 Липня, 2026
  • 14 views
Dependency Injection у Spring: пояснюємо на пальцях

Java Collections Framework: List, Set чи Map?

  • Автор javaadmin
  • 31 Липня, 2026
  • 29 views
Java Collections Framework: List, Set чи Map?

Оптимізуємо це: GraalVM Native Image, Leyden та CRaC

  • Автор javaadmin
  • 17 Липня, 2026
  • 57 views
Оптимізуємо це: GraalVM Native Image, Leyden та CRaC

JBang: Як вивчати Java легко

  • Автор javaadmin
  • 12 Травня, 2026
  • 130 views
JBang: Як вивчати Java легко

Agent Skills: Що це таке і чому про це варто знати

  • Автор javaadmin
  • 13 Квітня, 2026
  • 233 views
Agent Skills: Що це таке і чому про це варто знати

Dependency Injection в Java

  • Автор javaadmin
  • 9 Грудня, 2025
  • 407 views
Dependency Injection в Java