Часто выбор коллекции ограничивается только таблицей сложностей и на этом всё.
Но реальный кейс сложнее: средняя сложность ≠ реальная скорость в продакшне. JVM, кэш процессора, GC и паттерны доступа могут радикально поменять картину.
🔑 Главная мысль
Выбирайте коллекцию под сценарий использования, а не “по самой быстрой ячейке в таблице”.
ArrayList хранит элементы в массиве → локальность памяти + CPU кэш → итерации летят.
Вставка в середину за O(n), но при небольших списках разница с LinkedList исчезающе мала.
🔧 Паттерн использования:
— 90% чтение, редкие вставки → идеально.
— Если заранее известно примерное кол-во элементов → задайте initialCapacity, иначе ArrayList будет несколько раз пересоздавать массив (copy O(n) на каждом росте).
В бенчмарках JMH даже при вставке в середину ArrayList часто быстрее LinkedList просто потому, что LinkedList платит за “pointer chasing” (скачки по памяти, cache-miss).
Да, вставка/удаление в начало или конец за O(1).
Но get(i) = O(n), и каждый шаг = новый объект, новая ссылка → нагрузка на GC.
🔧 Паттерн использования:
— Когда нужна двусторонняя очередь с частыми удалениями/добавлениями в начало и конец.
— Во всех остальных случаях лучше ArrayDeque, он без лишних объектов и быстрее почти всегда.
LinkedList ест больше памяти: на каждый элемент два указателя + объект-узел.
HashMap даёт O(1) доступ при хорошем hashCode().
Но:
— Если хэши “плохие” → коллизии → O(log n)
— При достижении load factor 0.75 → resize → перераспределение всех бакетов (дорогая операция).
🔧 Паттерн использования:
— Когда нужен быстрый поиск по ключу без сохранения порядка или когда важно хранить уникальные элементы или строить словари/кэши по ключу.
— Если знаете примерное кол-во элементов → сразу задайте кол-во элементов в конструкторе new HashMap<>(N).
Начиная с Java 8 при коллизии, когда LinkedList становится длинным (по умолчанию ≥ 8 элементов) → список превращается в красно-чёрное дерево.
Дают O(log n) доступ и всегда хранят ключи отсортированными.
Но если сортировка нужна редко, дешевле собрать HashMap и вызвать sorted() на стриме.
🔧 Паттерн использования:
— Когда важно поддерживать сортировку на каждой операции (напр. Top-N задач в приоритетной очереди).
— Не храните mutable-ключи, т.к. можно “потерять” элемент при изменении поля, участвующего в compareTo.
TreeMap хранит узлы с балансировкой (красно-чёрное дерево) → накладные расходы на память + сравнения ключей.
LinkedHashMap поддерживает порядок вставки или порядок доступа (accessOrder=true).
Можно сделать LRU-кэш, переопределив removeEldestEntry.
🔧 Паттерн использования:
— Когда важен порядок, но сортировка не нужна.
— Когда нужно легко реализовать ограниченный кэш.
Каждый get() в режиме accessOrder вызывает перестановку в двусвязном списке → небольшие накладные расходы.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22❤9🔥4
💎 Как работает String.intern() под капотом
Многие знают, что строки в Java «живут в пуле». Но что реально происходит, когда мы вызываем intern()?
1️⃣ Что такое String Pool
Java хранит все строковые литералы в специальной области памяти — String Intern Pool. Зачем? Чтобы одинаковые строки не занимали память несколько раз.
Обе ссылки указывают на одну и ту же строку из пула.
2️⃣ Как работает intern()
Если вызвать s.intern():
— JVM проверит, есть ли такая строка в пуле.
— Если есть, вернёт ссылку на неё.
— Если нет, добавит текущую строку в пул и вернёт ссылку.
Пример:
3️⃣ Под капотом JVM
🔹 До Java 7 String Pool находился в PermGen → можно было легко словить OOM.
🔹 Начиная с Java 7 (HotSpot) пул перенесли в heap, что сильно упростило жизнь.
🔹 Реализация — ConcurrentHashMap внутри JVM, так что intern() потокобезопасен.
4️⃣ Где это полезно
🔹 Оптимизация памяти при большом количестве одинаковых строк (например, при парсинге XML/JSON).
🔹 Сравнение строк через == (только если они гарантированно interned).
🔹 При работе с ключами в больших мапах, чтобы уменьшить дубли.
5️⃣ Подводные камни
🔹 intern() не бесплатен — поиск в пуле и вставка стоят ресурсов.
🔹 Чрезмерное использование может привести к росту heap-а и GC-паузам.
🔹 Нельзя бездумно использовать вместо обычных строк → легко получить деградацию.
🔗 Документация: String.intern()
💬 Использовали когда-нибудь intern() в продакшене?
🐸 Библиотека джависта
#CoreJava
Многие знают, что строки в Java «живут в пуле». Но что реально происходит, когда мы вызываем intern()?
Java хранит все строковые литералы в специальной области памяти — String Intern Pool. Зачем? Чтобы одинаковые строки не занимали память несколько раз.
String a = "hello";
String b = "hello";
System.out.println(a == b); // true
Обе ссылки указывают на одну и ту же строку из пула.
Если вызвать s.intern():
— JVM проверит, есть ли такая строка в пуле.
— Если есть, вернёт ссылку на неё.
— Если нет, добавит текущую строку в пул и вернёт ссылку.
Пример:
String x = new String("world");
String y = x.intern();
String z = "world";
System.out.println(x == z); // false
System.out.println(y == z); // true
🔹 До Java 7 String Pool находился в PermGen → можно было легко словить OOM.
🔹 Начиная с Java 7 (HotSpot) пул перенесли в heap, что сильно упростило жизнь.
🔹 Реализация — ConcurrentHashMap внутри JVM, так что intern() потокобезопасен.
🔹 Оптимизация памяти при большом количестве одинаковых строк (например, при парсинге XML/JSON).
🔹 Сравнение строк через == (только если они гарантированно interned).
🔹 При работе с ключами в больших мапах, чтобы уменьшить дубли.
🔹 intern() не бесплатен — поиск в пуле и вставка стоят ресурсов.
🔹 Чрезмерное использование может привести к росту heap-а и GC-паузам.
🔹 Нельзя бездумно использовать вместо обычных строк → легко получить деградацию.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤3🤔2🔥1
Чтобы вам было проще ориентироваться в постах, мы разделили весь контент по 4 основным направлениям:
🔹 #CoreJava — фундаментальные знания: JVM, JDK, ООП, многопоточность, паттерны и базовые концепции. Всё, что помогает понимать Java глубже, а не просто «писать код, чтобы работало».
🔹 #Enterprise — прикладные инструменты и практика: Spring, Hibernate, Kafka, Docker, микросервисы. Всё, что встречается в работе разработчика каждый день.
🔹 #DevLife — сообщество и карьера: мемы, холивары, задачи с собесов, советы по развитию и личные рубрики. Всё, что создаёт атмосферу и объединяет нас как комьюнити.
🔹 #News — дайджесты, свежие анонсы, релизы и новости. А также реклама и инфоповоды, которые стоит знать.
👉 Используйте теги, чтобы быстро находить посты по интересующей теме.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥3👏1