Почему в Java интерфейсы Collection и Map разделены?

«Почему в Java интерфейсы Collection и Map разделены?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Интерфейсы Collection и Map разделены, потому что представляют фундаментально разные абстракции для хранения данных, что отражено в их API и контрактах.

Ключевые различия:

  • Абстракция данных: Collection<E> работает с единичными элементами типа E. Map<K, V> работает с парами ключ-значение, где каждый элемент — это ассоциация между уникальным ключом K и значением V.
  • Базовые операции:
    • Collection: add(E e), remove(Object o), contains(Object o).
    • Map: put(K key, V value), get(Object key), containsKey(Object key).
  • Итерация: Collection расширяет Iterable<E>, позволяя напрямую перебирать элементы. Для итерации по Map необходимо сначала получить представление в виде Collection (например, через entrySet(), keySet() или values()).

Пример, иллюстрирующий разницу в использовании:

// Collection — список элементов
List<String> list = new ArrayList<>();
list.add("element1");
list.add("element2");
for (String element : list) { /* ... */ }

// Map — ассоциативный массив
Map<String, Integer> map = new HashMap<>();
map.put("age", 30);
map.put("score", 100);
for (Map.Entry<String, Integer> entry : map.entrySet()) { /* ... */ }

Почему такое разделение — это хорошо:

  1. Четкость контракта: Каждый интерфейс имеет строго определенную семантику, что делает API предсказуемым.
  2. Упрощение архитектуры: Разделение соответствует принципу единой ответственности. Collection моделирует линейные или групповые структуры данных (списки, множества, очереди), а Map — ассоциативные массивы или словари.
  3. Эффективность: Реализации каждого интерфейса могут быть оптимизированы под свою специфическую задачу (например, хэш-таблицы для HashMap, красно-черные деревья для TreeMap).