Какие реализации интерфейса Map в Java вы знаете и в чем их ключевые отличия?

«Какие реализации интерфейса Map в Java вы знаете и в чем их ключевые отличия?» — вопрос из категории Основы программирования, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Map<K, V> в Java — интерфейс для хранения пар «ключ-значение». Основные реализации и их отличия:

Реализация Порядок итерации Допустимые ключи null Потокобезопасность Временная сложность (в среднем)
HashMap Не гарантирован Да (1 ключ) Нет O(1) для get()/put()
LinkedHashMap По порядку добавления или доступа (access-order) Да (1 ключ) Нет O(1)
TreeMap Отсортирован по ключам (натуральный порядок или Comparator) Нет Нет O(log n)
ConcurrentHashMap Не гарантирован Нет Да (оптимистичные блокировки) O(1)
Hashtable (устаревший) Не гарантирован Нет Да (полная синхронизация методов) O(1)

Ключевые моменты и best practices:

  • HashMap — самая распространенная реализация для общего случая. Использует хэш-таблицу.
  • LinkedHashMap — сохраняет порядок вставки, что полезно для кэшей (LRU) или когда важен порядок обхода. Можно настроить в режим access-order для LRU-кэша.
  • TreeMap — обеспечивает сортировку, но требует, чтобы ключи были сравнимы (Comparable). Использует красно-черное дерево.
  • ConcurrentHashMap — предпочтительный выбор для многопоточных сред. Обеспечивает высокую производительность за счет сегментированной блокировки.
  • Hashtable — устарел, не рекомендуется к использованию. Вместо него используйте ConcurrentHashMap.

Пример использования ConcurrentHashMap:

import java.util.concurrent.ConcurrentHashMap;

ConcurrentHashMap<String, Integer> userScores = new ConcurrentHashMap<>();
// Безопасные операции в многопоточной среде
userScores.put("Alice", 100);
userScores.computeIfPresent("Alice", (key, val) -> val + 50); // Атомарное обновление
System.out.println(userScores.get("Alice")); // 150