Java: fill the gaps
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк 🔥Тот самый курс по многопочке🔥 https://fillthegaps.ru/mt Комплименты, вопросы, предложения: @utki_letyat
显示更多📈 Telegram 频道 Java: fill the gaps 的分析概览
频道 Java: fill the gaps (@java_fillthegaps) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 12 552 名订阅者,在 技术与应用 类别中位列第 10 101,并在 俄罗斯 地区排名第 52 755 位。
📊 受众指标与增长动态
自 невідомо 创建以来,项目保持高速增长,吸引了 12 552 名订阅者。
根据 05 六月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -49,过去 24 小时变化为 -4,整体触达仍然可观。
- 认证状态: 未认证
- 互动率 (ER): 平均受众互动率为 34.71%。内容发布后 24 小时内通常能获得 N/A% 的反应,占订阅者总量。
- 帖子覆盖: 每篇帖子平均可获得 0 次浏览,首日通常累积 0 次浏览。
- 互动与反馈: 受众积极参与,单帖平均反应数为 0。
- 主题关注点: 内容集中在 redis, hashmap, linkedhashmap, индекс, фича 等核心主题上。
📝 描述与内容策略
作者将该频道定位为表达主观观点的平台:
“Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк
🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt
Комплименты, вопросы, предложения: @utki_letyat”
凭借高频更新(最新数据采集于 07 六月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。
@Query(value = "SELECT * FROM outbox
WHERE is_done = false
ORDER BY id ASC LIMIT 1
FOR UPDATE SKIP LOCKED",
nativeQuery = true
)
Optional<OutboxEntry> findFirstByIsDoneFalseOrderByIdAsc();
Теперь задачи обрабатываются параллельно несколькими сервисами🥳
P.S. Очень рада, что в прошлом опросе было много правильных ответов, вы умнички🥰UPDATE tasks SET status = 'in progress'
WHERE status = 'not processed'
RETURNING id, …;
Плюс: нет длинной транзакции
Минус: если сервис упадёт, задача останется в БД со статусом "в работе", и в итоге не будет обработана. Нужно дополнительно следить за такими ситуациями.
Итого
Блокировки работают до конца работы транзакции. Если полагаетесь на блокировки - не отпускайте их раньше времени.
Это просто, но в большой кодовой базе легко упустить этот момент. Будьте внимательнее❤️ Вторую проблему опишу в следующем посте!public class Button
private Lamp lamp;
public void push() {
// включить/выключить лампу
}
}
В мире с Dependency inversion Кнопка и Лампа ничего не знают друг о друге, логика взаимодействия описана в классе Электросхема. Она ловит сигналы от Кнопки и отправляет команды Лампе:
public class Circuit {
private Button button;
private Lamp lamp;
public void process() {
// получить сигнал от кнопки
// сказать лампе включиться / выключиться
}
}
Если у лампы появится новый режим, разбираться с этим будет электросхема, а не кнопка. Если кнопка поменяется на датчик движения, обработка поменяется только в электросхеме.
Интерфейсы можно добавить, чтобы жонглировать реализациями, но это не главное. Dependency inversion говорит о том, что логика взаимодействия компонентов должна находиться НЕ в самих компонентах.
Кстати, если перейти с уровня классов на уровень контроллеры/сервисы, получится Clean architecture. В основе та же идея: компоненты отдельно, взаимодействие отдельно.
Всё очень просто❤️Map<String, String> map = new HashMap<>();
Это считается реализацией DI? Чем отличается от инкапсуляции? Для каждого класса нужно создавать интерфейс? Работа с любым классом напрямую — это нарушение принципа? Почему в названии есть инвершн, что инвертируется-то?
Вопросы здравые, но люди в трансе:) У других абстрактных тем вроде принципов ООП или паттернов такого эффекта нет.
SOLID — самая унылая тема на собеседовании. Формальная, абстрактная и скучная для всех сторон. Собеседование длится всего час-полтора, нет никакого смысла тратить время на ритуальный обмен фразами.
❓ Применяются ли принципы SOLID на практике?
▫️ Single Responsibility - да. Что неудивительно, это самый понятный и простой принцип.
▫️ Open-closed, Liskov и Interface Segregation тесно связаны с наследованием и сложными иерархиями классов. Для бизнес логики большинства систем это не очень актуально. Там максимум интерфейс и несколько реализаций.
▫️ Dependency Inversion - самый непонятный и недооцененный принцип. За 10+ лет в разработке я встречала мало людей, которые его поняли. Это не просто "делаем всё через интерфейс". Можно реализовать его даже без интерфейсов, суть вообще в другом.
К четвергу напишу пост и подробно объясню🔥public class MapController {
private final Map<String, Object> map = new ConcurrentHashMap<>();
@PostMapping
public void putValue(@RequestParam String k, @RequestParam Object v) {
map.put(k, v);
}
@GetMapping
public Object getValue(@RequestParam String k) {
return map.get(k);
}
}
Задача: сравнить оба варианта. В расчет берём только базовую функцию - записать и прочитать ключ-значение из оперативной памяти.
В итоге получился очень интересный разговор. Люблю такое на собеседованиях😊
Ещё немного вводных, чтобы глубже погрузиться в вопрос.
Структура данных
В Redis используется простая хэш-таблица. Считаем хэш ключа, определяем бакет, добавляем в список. Алгоритм даже проще, чем в джаве. В джаве список перестраивается в дерево, когда элементов много. В Redis такого нет.
Многопоточный доступ
В Redis хэш-таблица никак не синхронизирована, безопасно работать может только один поток.
ConcurrentHashMap не зря называется concurrent. Область синхронизации при записи ограничена одним бакетом, т.е число одновременно пишущих потоков ~ числу бакетов. На чтение ограничений вообще нет.
Потенциально ConcurrentHashMap способен обслужить миллионы запросов одновременно. Redis в каждый момент времени работает с одним запросом.
Явный перевес в сторону нашего велосипеда🧐
На этом этапе кандидат согласился, что всё очень загадочно. И фраза, что Redis однопоточный и потому такой быстрый, звучит странно.
Почему же считается, что Redis лучше, и как он справляется с нагрузкой своим одним потоком? Об этом расскажу завтра❤️Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set = Collections.unmodifiableSet(set);
Просто скрыть эту логику за Set.of кажется неэффективным. Значений мало, они не будут меняться. Так и просится какая-нибудь оптимизация.
Зимой у меня выходил пост Как ускорить HashMap. Там я описала альтернативный алгоритм для сета, в котором значения лежат рядом и не надо прыгать по ссылкам по всей куче. Сейчас в джаве его применить нельзя из-за особенностей работы с объектами.
“Но ведь скоро мы реализуем value types!”: подумал Стюарт и взял этот алгоритм за основу Set.of.
Реализация Set.of - линейное пробирование в чистом виде. Сверху стоит аннотация @ValueBased - отметка для будущего использования value types.
Отсюда понятно, почему Set.of не принимает дубликаты и null: в концепции value types таких понятий просто не существует. Любая сущность уникальна и не может быть null. С этой точки зрения, поведение Set.of абсолютно логично.
Чем меня веселит эта история.
Работу над Project Valhalla начали в 2014. Java 9 и Set.of вышли в 2017. Сейчас 2025, прошло 8 лет.
Как говорится: если разработчики сказали, что сделают value types, они сделают. Не нужно напоминать об этом каждые полгода.
Задел на прекрасную джаву будущего понятен. Но по сути разработчики выкатили реализацию с оглядкой на фичу, которая не вышла и в обозримом будущем не выйдет. Очаровательно😄Set.of(1, 2, null)
получим NPE Cannot invoke "Object.hashCode()" because "pe" is null. Какая-то ошибка внутри реализации🤯
Поищем ответ в документации, точнее в JEP. Set.of появился в java 9, его цель обозначена явно - создать удобную альтернативу ручному заполнению сета:
// 8
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set = Collections.unmodifiableSet(set);
// 9
Set<String>set = Set.of(“a“, “b“);
Удобно, конечно, но альтернатива получилась не равнозначная.
Почему новый код не умеет фильтровать дубликаты? Почему не умеет работать с null? Почему “удобная” версия работает по-другому?
Я с джавой работаю давно, поэтому причину знаю и расскажу вам в следующем посте. А пока давайте оценим единственную версию из интернета:
🧔 Элементы задаются все и сразу, программист их видит. Если передаются дубликаты или null - это точно ошибка разработчика.
Здесь можно потренировать критическое мышление и подумать, что не так с этой версией.
А потом прочитать 3 причины:
✨ Не всегда значения наглядно записаны. Их могут передать через конструктор или через поля обьекта:
Set<Long> adminIds = Set.of(user1.getId(), user2.getId());
✨Бросать исключение в рантайме при подозрении на опечатку как-то слишком брутально
✨ Если мы не считаем null нормальным элементом, почему не отфильтровать его в начале? Почему мы видим NPE из глубин реализации?
Итого, вариант “чтобы разработчик был внимательнее” нам не подходит. Причина в чем-то другом.
Оставлю вас подумать над этим, а в следующем посте расскажу, почему Set.of такой странный. Там интересно😊
现已上线!2025 年 Telegram 研究 — 年度关键洞察 
