RU | EN | DE

Что такое коллекции

Коллекции в Java — это фреймворк (набор классов и интерфейсов), который упрощает работу с группами объектов: их хранение, поиск, сортировку, удаление и т. д. Вместо того чтобы самим писать массивы и методы для добавления/удаления элементов, Java предлагает готовые структуры данных. Коллекции живут в пакете java.util и объединены в Java Collections Framework (JCF).

Где используются

  • хранение данных (например, список пользователей или заказы в интернет-магазине);
  • поиск и фильтрация (например, все заказы дороже 100 €);
  • сортировка (по дате, алфавиту и т.д.);
  • работа с уникальными данными (например, список логинов без повторов);
  • сопоставление ключ–значение (карта настроек приложения или кэш).

Почему важно знать

  1. 90% задач в разработке связаны с хранением и обработкой данных.
  2. Коллекции экономят время — они уже оптимизированы и протестированы.
  3. Многие фреймворки (Spring, Hibernate) используют коллекции внутри себя

Основные интерфейсы коллекций

Всё крутится вокруг Collection и Map.

1) Интерфейс Collection

Подразделяется на:

  • List — упорядоченные списки, допускают дубликаты.
    • Реализации: ArrayList, LinkedList, Vector, Stack.
  • Set — множества, уникальные элементы.
    • Реализации: HashSet, LinkedHashSet, TreeSet.
  • Queue/Deque — очереди (FIFO, LIFO).
    • Реализации: PriorityQueue, ArrayDeque.

2) Интерфейс Map

Хранит пары ключ–значение.

  • Реализации: HashMap, LinkedHashMap, TreeMap, Hashtable, ConcurrentHashMap.

Иерархия Java Collections Framework

               Iterable

              Collection
      ┌───────────┼────────────────┐
      │           │                │
     List        Set          Queue/Deque
      │           │                │
  ┌───┴───┐    ┌──┴─────────┐  ┌───┴─────────┐
  ArrayList    HashSet          PriorityQueue
  LinkedList   LinkedHashSet    ArrayDeque
  Vector       TreeSet
  Stack    
 
        Map (НЕ наследуется от Collection)
         ┌─────────────┬───────────────┐
      HashMap     LinkedHashMap     TreeMap
      Hashtable   ConcurrentHashMap

Отличия коллекций

  • ArrayList — быстрый доступ по индексу, медленное удаление в середине.
  • LinkedList — медленный доступ по индексу, быстрое добавление/удаление.
  • HashSet — уникальные элементы, порядок не гарантируется
  • LinkedHashSet — сохраняет порядок вставки.
  • TreeSet — хранит элементы в отсортированном виде.
  • HashMap — пары ключ–значение, порядок не гарантируется.
  • LinkedHashMap — сохраняет порядок вставки.
  • TreeMap — хранит ключи в отсортированном виде.

Связь с другими концепциями

  • Generics: коллекции почти всегда используют обобщения (например, List<String>).
  • Stream API: коллекции часто конвертируются в стримы для удобной обработки (list.stream().filter(...).map(...).collect(...)).
  • Многопоточность: существуют конкурентные реализации (ConcurrentHashMap, CopyOnWriteArrayList).---

Пример кода

Мы посмотрим на:

  • ListArrayList, LinkedList
  • SetHashSet, TreeSet
  • MapHashMap, TreeMap И поймём, чем они отличаются на практике.
import java.util.*;
 
public class CollectionsDemo {
    public static void main(String[] args) {
        // ====== LIST ======
        List<String> arrayList = new ArrayList<>();
        arrayList.add("Java");
        arrayList.add("Python");
        arrayList.add("C++");
        arrayList.add("Java"); // допускает дубликаты
 
        System.out.println("ArrayList: " + arrayList);
 
        List<String> linkedList = new LinkedList<>();
        linkedList.add("First");
        linkedList.add("Second");
        linkedList.add("Third");
 
        System.out.println("LinkedList: " + linkedList);
 
        // ====== SET ======
        Set<String> hashSet = new HashSet<>();
        hashSet.add("One");
        hashSet.add("Two");
        hashSet.add("Three");
        hashSet.add("Two"); // дубликат игнорируется
 
        System.out.println("HashSet: " + hashSet);
 
        Set<String> treeSet = new TreeSet<>();
        treeSet.add("Banana");
        treeSet.add("Apple");
        treeSet.add("Orange");
 
        System.out.println("TreeSet (sorted): " + treeSet);
 
        // ====== MAP ======
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "One");
        hashMap.put(2, "Two");
        hashMap.put(3, "Three");
        hashMap.put(2, "NewTwo"); // перезапишет значение для ключа 2
 
        System.out.println("HashMap: " + hashMap);
 
        Map<Integer, String> treeMap = new TreeMap<>();
        treeMap.put(30, "Thirty");
        treeMap.put(10, "Ten");
        treeMap.put(20, "Twenty");
 
        System.out.println("TreeMap (sorted by key): " + treeMap);
    }
}
  • ArrayList — хранит порядок, допускает дубликаты.
    Вывод: [Java, Python, C++, Java].
  • LinkedList — тоже список, но оптимизирован для вставок/удалений.
  • HashSet — хранит только уникальные элементы, порядок непредсказуем.
  • TreeSet — уникальные + сразу сортировка.
  • HashMap — ключи уникальные, значения можно перезаписывать.
  • TreeMap — ключи отсортированы автоматически.

Типичные ошибки

  1. Забывают про generics:
List list = new ArrayList(); // raw type, плохо

Лучше так:

List<String> list = new ArrayList<>();
  1. Используют не ту коллекцию:
    • ArrayList вместо HashSet, если нужны уникальные значения.
    • LinkedList вместо ArrayList при большом количестве чтений по индексу.
  2. Сравнение через == вместо equals() для объектов в коллекциях.

Best practices

  • Используй интерфейс в объявлении (List, Set, Map), а не конкретный класс:
List<String> list = new ArrayList<>();
  • Выбирай коллекцию по задаче:
    • быстрый доступ по индексу → ArrayList
    • уникальные элементы → HashSet
    • сортировка → TreeSet / TreeMap
    • ключ-значение → HashMap

Шпаргалка по коллекциям

List (упорядоченные списки, допускают дубликаты)

КлассОсобенностиГде использовать
ArrayListБыстрый доступ по индексу O(1), медленное удаление/вставка в серединеКогда много чтения и редко меняется список
LinkedListБыстрая вставка/удаление O(1) в начале/середине, медленный доступ по индексуКогда нужно часто вставлять/удалять элементы
Vector / StackСтарые синхронизированные реализацииПочти не используются, лучше ArrayDeque

Set (множества, только уникальные элементы)

КлассОсобенностиГде использовать
HashSetНет порядка, уникальные элементы, быстрый поиск O(1)Когда нужны только уникальные значения
LinkedHashSetХранит порядок вставкиКогда нужны уникальные + порядок
TreeSetАвтоматическая сортировкаКогда нужны уникальные + сортировка

Map (ключ–значение)

КлассОсобенностиГде использовать
HashMapБыстрый доступ O(1), порядок не гарантированСамый популярный вариант (кэш, настройки и т.д.)
LinkedHashMapХранит порядок вставкиКогда важен порядок ключей
TreeMapАвтоматическая сортировка по ключуКогда нужен отсортированный словарь
ConcurrentHashMapПотокобезопасный, без блокировокДля многопоточности

Queue / Deque (очереди и стеки)

КлассОсобенностиГде использовать
ArrayDequeБыстрее чем Stack и LinkedListДля стека (LIFO) или очереди (FIFO)
PriorityQueueЭлементы сортируются по приоритетуДля очереди с приоритетом

Советы

  • Объявляй через интерфейс:
List<String> list = new ArrayList<>();
  • Для многопоточности используй Concurrent-версии (ConcurrentHashMap, CopyOnWriteArrayList).
  • Для больших данных и фильтраций — удобно переходить в Stream API.