Java: fill the gaps
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat
显示更多📈 Telegram 频道 Java: fill the gaps 的分析概览
频道 Java: fill the gaps (@java_fillthegaps) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 12 548 名订阅者,在 技术与应用 类别中位列第 10 113,并在 俄罗斯 地区排名第 52 819 位。
📊 受众指标与增长动态
自 невідомо 创建以来,项目保持高速增长,吸引了 12 548 名订阅者。
根据 08 六月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -43,过去 24 小时变化为 -3,整体触达仍然可观。
- 认证状态: 未认证
- 互动率 (ER): 平均受众互动率为 34.73%。内容发布后 24 小时内通常能获得 N/A% 的反应,占订阅者总量。
- 帖子覆盖: 每篇帖子平均可获得 0 次浏览,首日通常累积 0 次浏览。
- 互动与反馈: 受众积极参与,单帖平均反应数为 0。
- 主题关注点: 内容集中在 redis, hashmap, linkedhashmap, индекс, фича 等核心主题上。
📝 描述与内容策略
作者将该频道定位为表达主观观点的平台:
“Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк
🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt
Комплименты, вопросы, предложения: @utki_letyat”
凭借高频更新(最新数据采集于 09 六月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。
README.md в корневую директорию. Иногда это единственное, на что посмотрит посторонний человек. Не пожалейте времени, тщательно опишите:
▪️О чём проект
▪️Основные функции
▪️Архитектуру (нарисуйте схему)
▪️Используемые технологии
2️⃣ Проработайте структуру проекта - дайте модулям и классам понятные имена. Функции, указанные в README, должно быть легко найти в коде.
Эти простые действия помогут сориентироваться в проекте и лучше оценить Вашу работу.System.out.println.
Продвинутый вариант:
🔸Добавить брейкпойнт, зажав Shift.
🔸Щёлкнуть галочку Evaluate and log.
🔸Вписать нужное выражение.
В этом случае отладчик не будет останавливать выполнение, а запишет в консоль значение выражения. Очень полезно для отладки многопоточных приложений🔥 Дополнительный бонус: можно использовать в коде сторонних библиотек.
3️⃣ Отключение.
Если брейкпойнт пока не нужен, его можно не удалять, а отключить одним из двух способов:
▪️Щёлкнуть колёсиком по брейкпойнту.
▪️Правый щёлчок по брейкпойнту, снять галочку с Enabled.
4️⃣ Массовое удаление.
Когда в проекте очень много брейкпойнтов, IDE может подтормаживать при дебаге. Чтобы посмотреть полный список брейкпойнтов и удалить ненужные:
▫️Правый клик по любому брейкпойнту
▫️Ссылка More
▫️Слева видим список брейкпойнтов
▫️Удаляем ненужные
В этом же окне находятся фильтры для выборочной остановки, но обычно удобнее пользоваться условиями из п.1java.lang.String.
❓Почему для классов JDK используется 2 загрузчика?
✅ Bootstrap работает на уровне виртуальной машины и загружает необходимый минимум классов на старте приложения. Extension ClassLoader - java объект, который загружает дополнительные модули JDK по мере необходимости.
❓Почему для отложенной загрузки классов нужны разные ClassLoader?
✅ Для безопасности классов JDK. Cуществует 4 модификатора доступа - private, protected, public и default. Последний ещё называют "доступ по умолчанию". Он даёт доступ к классам и методам того же пакета. Если мы назовём класс java.lang.Smth, он сможет работать с классами из пакета java.lang. Поэтому класс получает доступ к default полям другого класса только если:
🔸У него совпадает название пакета.
🔸Загружен тем же ClassLoader'ом.
JDK классы используют Bootstrap/Extension загрузчик, а наш java.lang.Smth - Application загрузчик, поэтому внутренние классы JDK недоступны классу Smth.
❓Что изменилось в java 9?
✅ Схема взаимодействия загрузчиков осталась той же. Поскольку JDK библиотеки (rt.jar, tools.jar) теперь разбиты на модули, работа с ними поменялась:
1️⃣ Изменились внутренние классы и методы загрузчиков. Проекты, которые используют загрузчики классов напрямую, столкнулись с проблемами совместимости.
2️⃣ Extension ClassLoader переименован в Platform ClassLoader. Теперь он загружает классы из модулей JDK и сторонних библиотек, одобренных Java Community: JDBC, JMS, JAX-RS и т.д. .class. Когда в программе встречается имя нового класса, JVM "загружает" его: ищет файл с таким же именем и создаёт экземпляр типа Class. В этом объекте содержится информация о полях, методах и обо всём, что нужно для создания экземпляра.
Базовые классы JDK, такие как Object, String, ArrayList, являются основой для других объектов. Поэтому они загружаются на старте приложения, этим занимается объект JVM под названием Bootstrap ClassLoader.
Любая программа использует много сторонних библиотек. Чтобы не тратить ресурсы на загрузку лишних объектов, классы подгружаются по мере необходимости.
❓Какие события вызывают загрузку класса?
🔸Создание экземпляра:
new Example();🔸Ссылка на статические поля/методы этого класса:
Example.getFormat();🔸Явная загрузка класса:
cl.loadClass("Example");
Extension ClassLoader загружает редкие модули JDK: java.sql, jdk.httpserver и тд. Application ClassLoader загружает пользовательские классы.
Схема поиска подходящего .class файла выглядит так:char[].
В Java 9 вышло обновление Compact Strings, которое меняет структуру хранения строки.
Символы теперь лежат в byte[] и хранятся в одной из двух кодировок. Сама кодировка записана в новом параметре coder. Возможны 2 варианта:
1️⃣ Если все символы строки умещаются в 1 байт(латиница и цифры), то записываются в одну ячейку массива. Выставляется кодировка Latin-1.
2️⃣ Если хотя бы один символ требует 16 байт, все элементы занимают 2 ячейки массива. Выставляется кодировка UTF-16.
❓Можно ли было перевести строки на UTF-8, символы с переменной длиной?
Да, расход памяти стал бы ещё меньше, но производительность бы упала. Если символы в массиве одной длины, то по индексу можно быстро найти адрес символа в памяти. Если элементы с переменной длиной - адрес вычисляется на основе предыдущих элементов, а это долго. Все методы класса String работали бы дольше.
Строки в разных кодировках по-разному лежат в памяти, и работать с ними нужно тоже по-разному. Каждый метод в классе String начинается с проверки кодировки и разделяется на две ветки — для Latin-1 и UTF-16. Их код вынесен в отдельные классы StringLatin1 и StringUTF16.
❓Память сэкономили, кода стало в 3 раза больше, не упала ли производительность?
Любая дополнительная проверка снижает скорость обработки, особенно при работе с маленькими строками. Поэтому на уровне JVM и JIT добавлены оптимизации проверки кодировки и сравнения строк, изменён механизм конкатенации и других операций. Именно за счёт внутренних оптимизаций компактные строки работают в среднем на 20% быстрее и создают на 30% меньше промежуточных объектов.
Самое главное - эти изменения никак не отразились на интерфейсе String. I/O классы, StringBuilder, StringBuffer тоже адаптированы без внешних изменений. Нужно просто перейти на java 9 и приложение будет занимать на 5-15% меньше памяти.hash % 16 hash & 15Результат будет одинаковый, но логическое И выполняется в 2 раза быстрее. Вычисление бакета — частая операция в HashMap, и такая микрооптимизация даёт хороший прирост в производительности. ❓Что такое load factor и зачем он нужен? HashMap быстро работает, когда в бакете 0 или 1 элемент. При добавлении элементов повышается шанс, что в одном бакете их будет несколько, a HashMap станет менее эффективен. Поэтому HashMap периодически расширяется. Параметр load factor определяет, когда это происходит. По умолчанию равен 0.75. Пример: в HashMap 20 элементов и 32 бакета. Когда элементов будет 32*0.75=24, количество бакетов удвоится и элементы перераспределятся по ним. ❓Какие недостатки у HashMap? 1️⃣ Cильная зависимость от функции распределения хэшей. 2️⃣ Неэкономный расход памяти. При load factor = 0.75 будет пустовать 25% памяти. При неравномерном распределении хэшей — ещё больше. ❓В конструкторе HashMap проставляются свойства, а массив бакетов создаётся только при первой вставке. Зачем нужна ленивая инициализация? Расширение HashMap — долгая операция. Когда добавляется набор элементов, можно сразу увеличить массив до необходимого размера. Очень популярный случай - когда в пустой HashMap добавляютcя элементы другой map:
Map result=new HashMap(); ... result.putAll(anotherMap);Если бы внутренняя структура result создавалась в конструкторе, пришлось бы тут же её расширять. С отложенной инициализацией можно этого избежать. А теперь разберём вопрос про порядок элементов: ✅ Обход HashMap происходит последовательно - бакет за бакетом. Поэтому задание сводится к определению бакетов, в которые попадут значения. Это и будет порядок вывода элементов:
10 % 16 = 10 20 % 16 = 4 30 % 16 = 14Ответ: 20 10 30
String
▫️sout
System.out.println();
▫️main
public static void main(String[] args){}
▫️prsf
private static final
Некоторые сокращения разворачиваются в методы с параметрами для автозаполнения. Перемещаться между ними можно с помощью Tab:
▫️ fori
for (int i=0; i< ; i++) {}
▫️ifn
if (args == null) {}
▫️mx
= Math.max(, );
▫️lazy
if (obj == null)
{ obj = new Integer(); }
2️⃣ Code completion.
Дополнение имен классов, методов и полей на основе контекста. Варианты появляются в выпадающем списке. Можно писать только начало:
▫️Int → Integer
▫️Cust → Customer
Можно писать заглавные буквы в названиях классов:
▫️NPE → NullPointerException
▫️CHM → ConcurrentHashMap
Можно оборачивать код в синтаксические конструкции:
▫️count == 4.if
if (count == 4) {}
▫️list.for
for(Integer i : list) {}
▫️obj.opt
Optional.of(obj)
▫️answer.switch
switch (answer) {}
Полный список таких дополнений в File/Settings/Editor/General/Postfix Completion. Есть варианты не только для Java, но и для Kotlin и JS.Iterator it=list.iterator(); while(it.hasNext()) int result = it.next();Метод next() возвращает текущий элемент и сразу сдвигает указатель на следующий. Метод hasNext() проверяет, ссылается ли этот указатель куда-нибудь. Этот паттерн повторяется снова и снова и называется Iteration. Важно - указатель на следующий элемент вычисляется заранее. Итератор лежит в основе синтаксиса
for (T e: collection).
❌ Так как следующий элемент известен заранее, итератор может показать удалённый элемент. Или не вывести только что добавленный.
ArrayList, HashMap, HashSet и тд. не синхронизированы. Если одновременно итерировать и менять коллекцию разными потоками, можно нарушить целостность данных. Есть два способа этого избежать:
1️⃣ Fail-fast итераторы бросают ConcurrentModificationException при изменениях во время итерации.
2️⃣ Fail-safe итераторы работают с неизменяемой структурой.
Большинство однопоточных коллекций реализуют fail-fast подход.
ConcurrentHashMap потокобезопасен, поэтому изменения во время обхода разрешены. Обход через for реализован через итератор. Указатель на следующий элемент вычисляется заранее. Более подходящий новый элемент не отображается, и выводится 2 элемента.
Метод forEach в ConcurrentHashMap использует подход траверс и вычисляет следующий элемент только когда он запрашивается. Поэтому новый ключ подхватывается и выводится 3 элемента.
❓Почему нельзя использовать траверс по умолчанию?
➡️ Потому что итератор проще и работает быстрее, а условия для пропуска элемента при обходе встречаются редко.
❓Зачем нужно несколько вариантов?
➡️ ConcurrentHashMap может перестраиваться во время обхода. Чтобы во время перестройки не выводить пользователю дубликаты, используется траверс со сложной логикой.
Итого: при выводе элементов ConcurrentHashMap через for и forEach используются разные алгоритмы обхода, поэтому результат вывода тоже разный.
❗️Cинтаксис forEach реализован и для однопоточных коллекций, но там используется итератор, поэтому разницы с for нет.
现已上线!2025 年 Telegram 研究 — 年度关键洞察 
