Чем LinkedHashMap отличается от HashMap в Java?

Ответ

LinkedHashMap<K, V> — это реализация интерфейса Map, которая:

  1. Сохраняет порядок добавления элементов (по умолчанию) или порядок последнего доступа к ним.
  2. Наследуется от HashMap, используя его внутреннюю хеш-таблицу для быстрого доступа.
  3. Добавляет двусвязный список, соединяющий все записи для поддержания порядка.
Сравнение с HashMap: Особенность HashMap LinkedHashMap
Порядок итерации Не гарантирован, может меняться Гарантирован (порядок вставки или доступа)
Производительность Чуть быстрее на put()/get() Чуть медленнее из-за поддержки списка
Память Меньше накладных расходов Больше из-за хранения ссылок before/after
Итерация O(capacity) в худшем случае O(n), всегда пропорционально размеру

Пример: порядок вставки (по умолчанию)

Map<String, Integer> map = new LinkedHashMap<>();
map.put("z", 3);
map.put("a", 1);
map.put("b", 2);
// Итерация: z=3, a=1, b=2 (сохранен порядок put)
System.out.println(map); 

Пример: LRU-кэш на основе порядка доступа

// Третий параметр `true` включает режим порядка доступа (access-order)
Map<String, String> lruCache = new LinkedHashMap<>(16, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
        return size() > 3; // Удаляет самую старую запись при превышении лимита
    }
};

lruCache.put("1", "A");
lruCache.put("2", "B");
lruCache.put("3", "C");
lruCache.get("1"); // Обращение к "1" перемещает её в конец (самую новую)
lruCache.put("4", "D"); // Удалится "2", так как она стала самой старой (менее используемой)
// Состояние кэша: ["3"="C", "1"="A", "4"="D"]

Ответ 18+ 🔞

А, ну вот, смотри, это же тот самый случай, когда обычный HashMap тебе порядок хуй положил на блюдечко, а тебе надо, чтобы всё чинно-благородно, как в очереди за колбасой в девяностые. Так вот, LinkedHashMap<K, V> — это он самый, хитрожопый наследничек.

По сути, это всё тот же HashMap, но с прикрученным двусвязным списком, который все записи держит за ручки. Поэтому, когда ты итерируешь, они вылезают ровно в том порядке, в котором ты их туда пихал. Или, если специально попросишь, — в порядке, как к ним последний раз прикасались. Красота, а не структура.

Чем он от обычного HashMap отличается, спросишь? Давай на пальцах, только без мата... э, ладно, с матом.

Штука HashMap LinkedHashMap
Порядок Хуй пойми какой, как бог на душу положит. Чёткий, как у отличника в дневнике. Либо как добавлял, либо как трогал.
Скорость Чуть шустрее, потому что только хеши считает. Чуть тормознее, ибо ещё и ссылочки в списке перещёлкивает.
Память Жрёт поменьше. Жрёт побольше, потому что хранит два доп. указателя на каждую запись (before/after).
Обход В худшем случае — O(ёмкость), может быть долго. Всегда O(n), пропорционально размеру, ибо по цепочке.

Вот, смотри, как он порядок вставки хранит:

Map<String, Integer> map = new LinkedHashMap<>();
map.put("z", 3);
map.put("a", 1);
map.put("b", 2);
// Итерация: z=3, a=1, b=2 (сохранен порядок put)
System.out.println(map);

Видишь? Не перепутал "a" и "z", вывел ровно как ты впиндюрил. Не то что его беспорядочный папаша.

А теперь, внимание, ебаный цирк — режим доступа (access-order) и самописный LRU-кэш! Это когда элемент, к которому только что полезли, становится "самым свежим".

// Третий параметр `true` — это и есть волшебная кнопка "сортировать по доступу".
Map<String, String> lruCache = new LinkedHashMap<>(16, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
        // Вот тут решаем, выкидывать ли старейшую запись.
        // Скажем, если размер больше трёх — да, пошла нахуй.
        return size() > 3;
    }
};

lruCache.put("1", "A");
lruCache.put("2", "B");
lruCache.put("3", "C");
lruCache.get("1"); // Ткнули в "1" — она теперь "молодая", уехала в конец списка.
lruCache.put("4", "D"); // А тут лимит превысился! Кто самый старый и не тронутый? "2"! Её и удалит автоматом.
// Итого в кэше: ["3"="C", "1"="A", "4"="D"]

Вот так вот, блядь. Получается умная штука, которая сама выпиливает то, чем давно не пользовались. Ёперный театр, удобно же! Главное — не забывай, что за удобство всегда платишь чуть-чуть памятью и скоростью. Но иногда оно того стоит, особенно когда порядок — это не просто прихоть, а, блядь, требование.