← Назад к вопросам

Какие знаешь классы наследники Map?

1.3 Junior🔥 221 комментариев
#Коллекции

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Классы наследники Map в Java

Что такое Map

Map — это интерфейс, представляющий структуру данных, которая хранит пары ключ-значение. Каждый ключ должен быть уникален, а значение может быть null.

Map<String, Integer> map = new HashMap<>();
map.put("apple", 5);    // key="apple", value=5
map.put("banana", 3);   // key="banana", value=3

Integer count = map.get("apple");  // 5
map.remove("banana");

HashMap — самый используемый

Основная реализация Map, основанная на хеш-таблице. Не упорядочена, работает быстро.

Map<String, String> map = new HashMap<>();
map.put("Java", "Object-oriented");
map.put("Python", "Dynamic");
map.put("Go", "Concurrent");

// Порядок итерации может быть любым
for (String lang : map.keySet()) {
    System.out.println(lang);  // Может быть Python, Java, Go
}

// Время операций: O(1) в среднем
map.get("Java");     // O(1)
map.put("Rust", ""); // O(1)
map.remove("Go");     // O(1)

Характеристики:

  • Несинхронизированная (не thread-safe)
  • Быстрая (O(1) для основных операций)
  • Может быть null ключ и значения

TreeMap — упорядоченная по ключам

Основана на красно-чёрном дереве, ключи всегда отсортированы.

Map<String, Integer> map = new TreeMap<>();
map.put("zebra", 3);
map.put("apple", 5);
map.put("banana", 2);

// Итерация в порядке сортировки ключей
for (String key : map.keySet()) {
    System.out.println(key);
    // Вывод: apple, banana, zebra
}

// Дополнительные методы
String first = map.firstKey();      // "apple"
String last = map.lastKey();        // "zebra"
map.headMap("c");                  // Всё до "c"
map.tailMap("b");                  // Всё с "b"
map.subMap("a", "m");              // От "a" до "m"

// Время операций: O(log n)
map.get("apple");      // O(log n)
map.put("orange", 4);  // O(log n)

Характеристики:

  • Отсортирована по ключам
  • Медленнее HashMap (O(log n))
  • Не может быть null ключ, но может быть null значение
  • Требует сравнимости ключей (Comparable или Comparator)

LinkedHashMap — упорядоченная по порядку добавления

Основана на HashMap, но сохраняет порядок вставки элементов.

Map<String, Integer> map = new LinkedHashMap<>();
map.put("first", 1);
map.put("second", 2);
map.put("third", 3);

// Итерация в порядке добавления
for (String key : map.keySet()) {
    System.out.println(key);
    // Вывод: first, second, third
}

// LRU (Least Recently Used) кэш
map = new LinkedHashMap<>(16, 0.75f, true) {  // true = access order
    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > 3;  // Максимум 3 элемента
    }
};

map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
map.put("d", 4);  // "a" будет удалён (самый старый)

Характеристики:

  • Сохраняет порядок добавления или доступа
  • Немного медленнее HashMap из-за двусвязного списка
  • Идеален для реализации LRU кэшей
  • Может быть null ключ и значения

Hashtable — устаревшая синхронизированная

Старая реализация, синхронизирована, но медленнее ConcurrentHashMap.

Map<String, Integer> map = new Hashtable<>();
map.put("a", 1);
map.put("b", 2);

// Thread-safe, но весь метод синхронизирован
Integer value = map.get("a");

// ❌ Не используй! Используй ConcurrentHashMap

Характеристики:

  • Синхронизирована полностью
  • Медленная (весь метод заблокирован)
  • Не может быть null ключ
  • Наследуется из Dictionary (устаревший класс)

ConcurrentHashMap — современная многопоточная

Оптимизирована для параллельного доступа с помощью bucket-level блокировок.

Map<String, Integer> map = new ConcurrentHashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);

// Thread-safe без блокировки всей таблицы
Integer value = map.get("a");

// Несколько потоков могут одновременно писать в разные бакеты
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i = 0; i < 100; i++) {
    final int idx = i;
    executor.submit(() -> map.put("key" + idx, idx));
}

// Атомарные операции
map.putIfAbsent("d", 4);
map.remove("a", 1);  // Удалить только если значение == 1
map.replace("b", 2, 20);  // Заменить только если текущее значение == 2

// Итерация не блокирует другие потоки
for (String key : map.keySet()) {
    System.out.println(key);
}

Характеристики:

  • Thread-safe с segment-level блокировками
  • Быстра для многопоточного доступа
  • Не может быть null ключ, но может быть null значение
  • Идеальна для приложений с высоким параллелизмом

WeakHashMap — для автоматической очистки

Использует слабые ссылки на ключи, позволяя сборщику мусора удалять элементы.

Map<String, String> map = new WeakHashMap<>();
String key = "important";
map.put(key, "value");

System.out.println(map.size());  // 1
key = null;  // Ключ больше не используется
System.gc(); // Принудительная очистка мусора
System.out.println(map.size());  // Может быть 0

// Полезна для кэшей
Map<Class<?>, ClassMetadata> classMetadataCache = new WeakHashMap<>();
classMetadataCache.put(String.class, new ClassMetadata());
// Когда класс выгружается, запись в кэше автоматически удалится

Характеристики:

  • Ключи могут быть удалены сборщиком мусора
  • Полезна для кэшей и памяти
  • Медленнее HashMap

IdentityHashMap — по идентичности, не по equals

Использует == вместо equals() для сравнения ключей.

Map<String, String> map = new IdentityHashMap<>();

String key1 = new String("hello");
String key2 = new String("hello");

map.put(key1, "value1");
map.put(key2, "value2");

System.out.println(map.size());  // 2 (не 1!)
// Потому что key1 и key2 — разные объекты (== вернёт false)

map.get(key1);  // "value1"
map.get(key2);  // "value2"
map.get("hello");  // null (не equals ни одному ключу)

Характеристики:

  • Сравнивает по идентичности (==), не по equals
  • Очень быстрая
  • Редко используется

EnumMap — оптимизирована для enum ключей

Оптимизирована специально для использования enum в качестве ключей.

enum Color { RED, GREEN, BLUE }

Map<Color, String> map = new EnumMap<>(Color.class);
map.put(Color.RED, "#FF0000");
map.put(Color.GREEN, "#00FF00");
map.put(Color.BLUE, "#0000FF");

// Очень быстро и эффективно по памяти
// Внутри использует массив, не хеш-таблицу

for (Color color : Color.values()) {
    String hex = map.get(color);
    System.out.println(color + ": " + hex);
}

Характеристики:

  • Только для enum ключей
  • Очень быстрая (использует массив)
  • Экономна по памяти
  • Предсказуемый порядок итерации

SortedMap и NavigableMap интерфейсы

// SortedMap — отсортированная Map
SortedMap<String, Integer> sorted = new TreeMap<>();
sorted.put("c", 3);
sorted.put("a", 1);
sorted.put("b", 2);

Set<String> headSet = sorted.headMap("b").keySet();  // {"a"}
Set<String> tailSet = sorted.tailMap("b").keySet();  // {"b", "c"}

// NavigableMap — расширенная SortedMap
NavigableMap<String, Integer> nav = new TreeMap<>();
String floor = nav.floorKey("b");    // Наибольший <= "b"
String ceiling = nav.ceilingKey("b"); // Наименьший >= "b"
String higher = nav.higherKey("b");   // Наименьший > "b"
String lower = nav.lowerKey("b");     // Наибольший < "b"

Сравнительная таблица

КлассУпорядочиваниеThread-SafeПроизводительностьNull ключNull значение
HashMapНетНетO(1)ДаДа
TreeMapПо ключамНетO(log n)НетДа
LinkedHashMapПо добавлениюНетO(1)ДаДа
ConcurrentHashMapНетДаO(1)НетНет
HashtableНетДаO(1)НетНет
WeakHashMapНетНетO(1)ДаДа
IdentityHashMapНетНетO(1)ДаДа
EnumMapПо enumНетO(1)НетДа

Когда использовать какую

// Стандартный случай
Map<String, Integer> map = new HashMap<>();

// Нужна сортировка
Map<String, Integer> sorted = new TreeMap<>();

// Нужна многопоточность
Map<String, Integer> concurrent = new ConcurrentHashMap<>();

// Нужен LRU кэш
Map<String, String> lruCache = new LinkedHashMap<>(16, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > MAX_SIZE;
    }
};

// Нужны enum ключи
Map<Status, Integer> statusCounts = new EnumMap<>(Status.class);

// Нужна слабая ссылка
Map<ClassName, Metadata> classCache = new WeakHashMap<>();

Лучшие практики

  1. HashMap по умолчанию — быстрая и удобная
  2. TreeMap для сортировки — но медленнее
  3. ConcurrentHashMap для многопоточности — никогда не используй synchronized HashMap
  4. LinkedHashMap для LRU — эффективнее собственной реализации
  5. EnumMap для enum ключей — оптимальна по памяти
  6. Не используй Hashtable — это история

Выбор правильной реализации Map критичен для производительности приложения.