Какие коллекции типа «ключ-значение» вы использовали в Java и в чём их различия?

Ответ

Основные реализации интерфейса Map<K, V> в Java:

  • HashMap — хэш-таблица без гарантий порядка элементов. Допускает один null-ключ и множество null-значений. Не синхронизирована. Обеспечивает константное время O(1) для операций get() и put() в среднем случае.
  • LinkedHashMap — расширяет HashMap, сохраняя порядок вставки элементов (или порядок доступа, если используется режим access-order). Немного медленнее HashMap из-за поддержки связанного списка.
  • TreeMap — реализует интерфейс SortedMap. Хранит элементы в отсортированном порядке по ключам (на основе их натурального порядка или переданного Comparator). Основана на красно-чёрном дереве, операции get(), put() выполняются за O(log n).
  • Hashtable — устаревшая синхронизированная версия. Не допускает null-ключи или значения. Для многопоточности предпочтительнее использовать ConcurrentHashMap.
  • ConcurrentHashMap — высокопроизводительная, потокобезопасная реализация. Использует сегментирование блокировок (в более новых версиях — CAS-операции) для лучшего параллелизма.

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

Map<String, Integer> inventory = new HashMap<>();
inventory.put("apples", 50);
inventory.put("oranges", 30);
Integer appleCount = inventory.get("apples"); // 50
boolean hasBananas = inventory.containsKey("bananas"); // false

Выбор реализации:

  • Скорость и порядок не важенHashMap.
  • Нужен порядок вставки/доступаLinkedHashMap.
  • Требуется сортировка по ключуTreeMap.
  • ПотокобезопасностьConcurrentHashMap.

Ответ 18+ 🔞

Давай разберём эти ваши мапы, как говорится, по косточкам, чтобы не путаться в трёх соснах, а точнее, в пяти реализациях. Ситуация, блядь, такая: интерфейс Map<K, V> — это как общая идея «ключ-значение», а под ним прячется целая орава конкретных ребят, у каждого свой характер, блядь.

Вот они, главные действующие лица:

  • HashMap — это наш основной работяга, быстрый и простой. Внутри у него, блядь, хэш-таблица, поэтому он элементы как попало складывает, порядка никакого не гарантирует, ему похуй. Зато один null-ключ засунуть можно и сколько угодно null-значений — не заартачится. Синхронизации нет, поэтому в одном потоке он летает как угорелый, операции get() и put() в среднем за O(1) делает. Но если его из нескольких потоков дёргать — будет пиздец и данные поплывут.

  • LinkedHashMap — это сынок HashMap, но более воспитанный. Он всё то же самое умеет, но порядок вставки элементов запоминает (или, если его специально попросить, порядок последнего доступа к ним). За эту аккуратность платит чуть меньшей скоростью, потому что там ещё связный список между элементами болтается. Но зато итерируешь — и они в том же порядке, в котором ты их пихал, красота.

  • TreeMap — это уже интеллигент, блядь. Реализует SortedMap и хранит всё по полочкам, отсортированно по ключам. Либо по их натуральному порядку (Comparable), либо как скажешь (Comparator). Внутри — красно-чёрное дерево, поэтому операции get(), put() у него за O(log n), помедленнее, зато всегда в порядке. Null-ключи, ёпта, не любит, может истерику закатить.

  • Hashtable — это дедушка, которого все уже забыли, но он из принципа ещё тут. Синхронизированный, старый, медленный. Null-ключи и значения в него совать — это как на ёлку залезть голой жопой: больно и бесполезно, кинет NullPointerException. Для многопоточности сейчас все умные люди берут ConcurrentHashMap и даже не смотрят в сторону этой развалины.

  • ConcurrentHashMap — это HashMap, который съел стероидов для многопоточности. Высокопроизводительный, умный, потокобезопасный. Не блокирует всю таблицу целиком, а хитрожопо работает с сегментами или CAS-операциями, чтобы все потоки не стояли в одной очереди. Для серьёзных многопоточных дел — это ваш выбор, ебать его в сраку.

Вот, смотри, как HashMap в деле выглядит, простой пример:

Map<String, Integer> inventory = new HashMap<>();
inventory.put("apples", 50);
inventory.put("oranges", 30);
Integer appleCount = inventory.get("apples"); // 50
boolean hasBananas = inventory.containsKey("bananas"); // false

А теперь, блядь, главный вопрос: кого брать-то?

  • Надо просто быстро и порядок не важен — бери HashMap и не парься.
  • Порядок вставки или доступа надо помнить — тебе в LinkedHashMap.
  • Ключи надо отсортировать, как в библиотеке — тогда TreeMap, без вариантов.
  • Работаешь из нескольких потоков и не хочешь словить рассинхрон мозгов — только ConcurrentHashMap, и даже не думай про Hashtable, это прошлый век, блядь.