Ответ
LinkedHashMap<K, V> — это реализация интерфейса Map, которая:
- Сохраняет порядок добавления элементов (по умолчанию) или порядок последнего доступа к ним.
- Наследуется от
HashMap, используя его внутреннюю хеш-таблицу для быстрого доступа. - Добавляет двусвязный список, соединяющий все записи для поддержания порядка.
Сравнение с 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"]
Вот так вот, блядь. Получается умная штука, которая сама выпиливает то, чем давно не пользовались. Ёперный театр, удобно же! Главное — не забывай, что за удобство всегда платишь чуть-чуть памятью и скоростью. Но иногда оно того стоит, особенно когда порядок — это не просто прихоть, а, блядь, требование.