Java: fill the gaps
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat
Show more📈 Analytical overview of Telegram channel Java: fill the gaps
Channel Java: fill the gaps (@java_fillthegaps) in the Russian language segment is an active participant. Currently, the community unites 12 548 subscribers, ranking 10 113 in the Technologies & Applications category and 52 819 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 12 548 subscribers.
According to the latest data from 08 June, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by -43 over the last 30 days and by -3 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 34.73%. Within the first 24 hours after publication, content typically collects N/A% reactions from the total number of subscribers.
- Post reach: On average, each post receives 0 views. Within the first day, a publication typically gains 0 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 0.
- Thematic interests: Content is focused on key topics such as redis, hashmap, linkedhashmap, индекс, фича.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк
🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt
Комплименты, вопросы, предложения: @utki_letyat”
Thanks to the high frequency of updates (latest data received on 09 June, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.
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)
Available now! Telegram Research 2025 — the year's key insights 
