Java: fill the gaps
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat
显示更多📈 Telegram 频道 Java: fill the gaps 的分析概览
频道 Java: fill the gaps (@java_fillthegaps) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 12 549 名订阅者,在 技术与应用 类别中位列第 10 120,并在 俄罗斯 地区排名第 52 841 位。
📊 受众指标与增长动态
自 невідомо 创建以来,项目保持高速增长,吸引了 12 549 名订阅者。
根据 07 六月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -46,过去 24 小时变化为 0,整体触达仍然可观。
- 认证状态: 未认证
- 互动率 (ER): 平均受众互动率为 34.72%。内容发布后 24 小时内通常能获得 N/A% 的反应,占订阅者总量。
- 帖子覆盖: 每篇帖子平均可获得 0 次浏览,首日通常累积 0 次浏览。
- 互动与反馈: 受众积极参与,单帖平均反应数为 0。
- 主题关注点: 内容集中在 redis, hashmap, linkedhashmap, индекс, фича 等核心主题上。
📝 描述与内容策略
作者将该频道定位为表达主观观点的平台:
“Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк
🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt
Комплименты, вопросы, предложения: @utki_letyat”
凭借高频更新(最新数据采集于 08 六月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。
record Point(int x, int y) {}
Создаются так же, как и другие классы:
Point p = new Point(1,2);В чём особенность? 🔸 Поля нельзя поменять: ни внутри методов, ни через рефлекшн 🔸 Нет приватных полей 🔸 Не участвуют в наследовании 🔸 Конструктор по умолчанию не пустой, а с заданными полями 🔸 Добавлены геттеры по умолчанию:
p.x() p.y()🔸 toString по умолчанию
Point[x=1, y=2]🔸 equals и hashcode по умолчанию 🔸 Для сериализации не нужен serialVersionUID Запись - специальный класс для хранения данных.
record Point компилируется в
public final class Point extends java/lang/RecordВсе остальные функции класса сохраняются: ✅ Определять методы ✅ Реализовать интерфейсы ✅ Добавлять static поля и методы ✅ Ставить аннотации ✅ Использовать дженерики Ещё одна особенность records — конструктор. Конструктор по умолчанию содержит все поля и называется канонический конструктор:
public Point(int x, int y){
this.x=x;
this.y=y;
}
Он доступен по умолчанию, его можно не писать. Переопределяйте конструктор, если нужно добавить проверку аргументов:
public Point(int x, int y){
if (x>100) throw new …
this.x=x;
this.y=y;
}
Для канонического конструктора есть краткая запись. Можно опустить присвоение переменных и оставить только нужные проверки:
public Point {
if (x>100) throw new ...
}
Другие конструкторы должны вызывать канонический:
public Point(int x) {
this(x,0);
}
Где использовать записи:
1️⃣ В многопоточных алгоритмах
Неизменяемые значения не нужно синхронизировать.
2️⃣ Data Transfer Object (DTO)
Для отправки данных пользователю или в другую систему.
record UserDTO(long id, String name) {
public UserDTO(User user) {…}
}
3️⃣ Как промежуточные значения в Stream API
Для упрощения сложного кода и большей читаемости.
4️⃣ Как составное возвращаемое значение
Когда не хочется создавать отдельный класс ради одного метода:
record MinMax<T>(T min, T max) {}
❗️Правильный ответ на вопрос перед постом:
В записях поля неизменны, также записи не участвуют в наследовании и не содержат приватных полей.360: Sealed Classes (Preview) 383: Foreign-Memory Access API (Second Incubator) 384: Records (Second Preview)Чем ближе выход java, тем больше статей о новых фичах — records, text blocks, sealed classes и т. д. Многие разработчики грустят: — Скоро java 15 выйдет, а в проекте 8 версия. Технологии идут вперёд, а я трачу лучшие годы на легаси(( У всех крупных проектов такая ситуация. Ближайшая LTS версия java выйдет в сентябре 2021. Большинство фич, о которых пишут статьи, сейчас в превью стадии. Они не доступны по умолчанию и войдут в обиход большинства проектов не раньше конца 2021 года. Но можно попробовать уже сейчас: 1️⃣ Intellij IDEA File → Project Structure → Project → Project Language Level В списке выбрать версию с пометкой (Preview) 2️⃣ Maven В плагины, которые работают с кодом (maven-compiler-plugin, maven-surefire-plugin) добавить секцию
<configuration> <argLine>--enable-preview</argLine> </configuration>3️⃣ При компиляции через консоль добавить 2 аргумента javac --release 13 --enable-preview Обратная связь по превью фичам собирается в Java Bug Database.
Ctrl + C
Ctrl + V
Ctrl + X
работают со всей строкой, на которой стоит курсор, не нужно ничего выделять.
Удалить всю строку:
Ctrl + YДублировать строку:
Ctrl + DЧтобы выделить часть кода:
Ctrl + WПри каждом нажатии W захватывается всё большая область. Чтобы переместить выделенный код:
Ctrl + Shift + ⬆️
Ctrl + Shift + ⬇️if (opt.isPresent()) {
return opt.get();
} else return "default";
используйте метод orElse:
✅ return opt.orElse("default");
❗️ Используйте orElse только с константами или простыми операциями, потому что выражение в orElse вычисляется всегда:
❌ getFromCache(id)
.orElse(getFromDB(id)
getFromDB выполнится, даже если getFromCache вернёт результат. Для тяжёлых операций используйте метод orElseGet:
✅ getFromCache(id)
.orElseGet(()→getFromDB(id))
Здесь getFromDB выполнится, только если результат getFromCache пустой.
2️⃣ Бросить эксепшн, если результата нет: orElseThrow
return opt.orElseThrow(NotFoundException::new)В Java 10 появился метод без параметров:
opt.orElseThrow()Если в opt нет значения, код выбросит NoSuchElementException. 3️⃣ Проверка условия: filter Вместо isPresent + get + проверка условия используйте метод filter:
value.filter(v→v.length()<4)
.ifPresent(…)
4️⃣ Преобразования: map / flatMap
Для манипуляций значением Optional используйте метод map:
opt.map(Account::getAddress)
.map(String::toUpperCase)
.orElse("default");
flatMap используется, если метод отображения возвращает Optional
Optional<String>getAddress(){…}
opt.flatMap(Account::getAddress)
5️⃣ Методы для Stream API (Java 9)
Когда в стриме один метод возвращает Optional, его часто обрабатывают так:
❌.filter(Optional::isPresent)
.map(Optional::get)
Метод flatMap пригодится и здесь. Все пустые значения отфильтруются:
✅ .flatMap(Optional::stream)
6️⃣ Сравнение Optional
Обычно делают так:
op1.get().equals(op2.get())❌ Если хотя бы один Optional пустой, будет NullPointerException Сравнивайте Optional напрямую: ✅
op1.equals(op2)
Ответ на задачу перед постом
Независимо от успеха getFromCache, метод orElse выполнится в любом случае, поэтому ответ
CACHE DB 15Чтобы не выполнять лишний код, используйте метод orElseGet
Optional<String> search()Самые частые ошибки при использовании: 1️⃣ Входные параметры Optional в методах и конструкторах Класс становится неудобным, приходится добавлять лишние обёртки и подгонять параметры. ❌
void init(Optional<String> value) {…}
Проверяйте параметры на null в начале метода:
✅ void init (String value) {
if (value == null) …
}
2️⃣ Усложнение кода
С появлением Stream API усилился тренд на Fluent API: это когда действия соединяются в одну цепочку. Не создавайте Optional только ради этого, пишите простой код.
❌return Optional.ofNullable(value).orElse("default");
✅return value==null ? "default":value;
3️⃣ Отложенная обработка Optional
Идеально, если обработка происходит сразу после возвращения из метода:
Optional<String> valueOpt = …
String value = valueOpt.orElse("default");
4️⃣ Optional с коллекциями
Возвращайте пустой список, если элементов нет:
❌ public Optional<List<Integer>> search(…)
✅ public List<Integer> search(…)
5️⃣ Работа с примитивами
Для примитивов int, long и double используйте специальные Optional классы:
✅ OptionalInt
✅ OptionalDouble
✅ OptionalLong
Нет затрат на создание объекта, а код становится чуть короче и понятнее. Методов меньше, чем в Optional, но при интенсивной работе с примитивами возможен прирост производительности.
Ответ на вопрос перед постом
❌ List<Student> search(Optional<String> city)
❌ void init(Optional<String> conf)
Входные параметры лучше проверять внутри метода
❌ Optional<List<Student>> all()
Лучше вернуть пустой список, если элементов нетpublic sealed class Shape permits Circle, RectangleКлассы, которых нет в блоке permits, не могут наследоваться от sealed класса. Проверка идёт во время компиляции или в IDE. В Intellij IDEA уже в июле добавили поддержку sealed типов. Плюс в java.lang.Class добавилось два метода:
🔸ClassDesc[] getPermittedSubclasses() 🔸boolean isSealed()❓Зачем? Глобальная цель - поддержка pattern matching. Чтобы вместо
if (s instanceof Circle) {…}
else if (s instanceof Rectangle) {…}
использовать switch:
switch (s) {
case Circle c -> …
case Rectangle r -> …
❓Где пригодятся sealed классы?
При реализации паттерна State. Раньше конечный набор состояний выражался только через enum:
enum State {NEW, VERIFIED;}
❌ Все элементы и методы хранятся вместе. Если методов много, то размер файла растёт, и читаемость снижается.
❌ Значения в конструкторе жёстко задаются на этапе компиляции.
enum State {
NEW(12);
int rating;
State(int rating) {…}
}
Теперь с помощью sealed класса:
✅ Каждое состояние в отдельном файле.
✅ Экземпляры создаются во время работы программы. Конструктор принимает параметры, а не константы.String s = new String("Java");
Откроем Memory View. После выполнения строки напротив класса java.lang.String увидим Diff +2.
Поменяем код на
String java = "Java";
String s = new String("Java");
Запустим снова. "Java" в первой строке отправилась в String pool. Теперь после выполнения второй строки напротив java.lang.String будет Diff +1.byte[] value — текст
byte coder — тип кодировки
int hash1️⃣ String Deduplication (Java 8) При использовании оператора new в памяти создаётся новый объект:
String str = new String("12");
Отдельный JVM поток ищет в памяти экземпляры String и записывает их текст в хэш-таблицу:
hash → byte[]Если поток находит дубликат, то заменяет ссылку в повторяющейся строке на ссылку из хэш-таблицы:
str.value = hashtable.valueНа текст дубликата больше нет ссылок, поэтому он удалится сборщиком мусора. Так можно сэкономить 5-30% памяти. Опция String Deduplication работает только со сборщиком G1, и по умолчанию отключена. ❓Почему заменяется только текст, а не вся строка? Ссылки на строчку могут быть в десятках мест. Текст — внутреннее поле, его заменить гораздо проще ❓Почему совместим только с G1? Нашла только один комментарий по теме: G1 – единственный сборщик мусора, в котором есть pinned regions. Это области, в которых не происходит дефрагментация. Но почему нельзя разместить хэш-таблицу в другом месте — непонятно😕 ❓Почему опция по умолчанию не работает? Deduplication хорошо экономит память, когда в программе через оператор new создаётся много похожих строк-долгожителей. Тогда экономится больше памяти, чем затраты на копирование в хэш-таблицу. По статистике OpenJDK таких случаев мало, поэтому StringDeduplication по умолчанию отключен. Для активации добавьте при запуске VM флажок:
-XX:+UseStringDeduplicationЧтобы посмотреть, сколько памяти сэкономил Deduplication, можно вывести статистику Xlog:
-Xlog:stringdedup*=debug2️⃣ Оптимизация хэш-кода (Java 13) Хэшкод строки играет важную роль в хэш-таблицах String pool, Deduplication и других процессах JVM. Внутри класса String хэш хранится как примитив:
int hashВычисляется и сохраняется при первом вызове hashcode():
if (hash == 0) {
hash = ...
}
⛔️Минус такого решения:
Если хэш равен 0, то он пересчитывается каждый раз. Шанс этого очень низкий, но в Java 13 в String добавился флаг для нулевого хэша:
boolean hashIsZeroПроверка того, что хэш-код ещё не посчитан, стала такой:
if (h == 0 && !hashIsZero)Теперь хэш-код всегда считается один раз. Итого: оптимизацией строк идёт по всем фронтам: 1️⃣ Структура данных (Java 9: Compact Strings) 2️⃣ Кэширование (String pool) 3️⃣ Оптимизация частных случаев (Java 8: String Deduplication) 4️⃣ Микрооптимизации (Java 13: флажок hashIsZero)
现已上线!2025 年 Telegram 研究 — 年度关键洞察 
