Что такое интерфейс Map в Java и каковы его основные реализации?

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

Ответ

java.util.Map<K, V> — это интерфейс, представляющий коллекцию пар "ключ-значение". Ключи уникальны в рамках одной мапы, значения могут повторяться. Map не является подтипом Collection.

Основные реализации и их характеристики:

Реализация Порядок итерации Допустимые null Временная сложность (в среднем) Лучше всего подходит для
HashMap Не гарантируется. Ключ: да (1), Значение: да. O(1) для get() и put(). Универсального кэширования, быстрого поиска по ключу.
LinkedHashMap По порядку вставки (или порядку доступа). Ключ: да (1), Значение: да. O(1) для get() и put(). Кэшей LRU, сохранения порядка вставки.
TreeMap По возрастанию ключей (натуральный порядок или Comparator). Ключ: нет, Значение: да. O(log n) для get() и put(). Хранения отсортированных данных, работы с диапазонами ключей.
ConcurrentHashMap Не гарантируется. Нет (ни ключ, ни значение). O(1) для get() (неблокирующий), O(1) для put(). Многопоточных сценариев без явной синхронизации.
Hashtable (устаревший) Не гарантируется. Нет (ни ключ, ни значение). O(1) для get() и put(). Не рекомендуется. Используйте ConcurrentHashMap.

(1) В HashMap разрешен только один ключ null.

Базовые операции:

Map<String, Integer> scores = new HashMap<>();

// Добавление и обновление
scores.put("Alice", 95);     // Добавляет пару
scores.put("Bob", 87);
scores.put("Alice", 100);    // Обновляет значение для ключа "Alice"

// Получение
int aliceScore = scores.get("Alice"); // 100
Integer charlieScore = scores.get("Charlie"); // null (ключа нет)

// Проверка существования
boolean hasBob = scores.containsKey("Bob"); // true
boolean hasScore100 = scores.containsValue(100); // true

// Итерация
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Alice: 100
// Bob: 87

// Полезные методы Java 8+
scores.getOrDefault("Charlie", 0); // Возвращает 0, если ключа нет
scores.putIfAbsent("Bob", 99); // Добавит, только если ключа ещё нет (не добавит)
scores.forEach((k, v) -> System.out.println(k + " -> " + v));