java_library | Unsorted

Telegram-канал java_library - Java Books

14242

Java Библиотека По всем вопросам- @notxxx1 @ai_machinelearning_big_data - machine learning @pythonl - Python @itchannels_telegram - 🔥 best it channels @ArtificialIntelligencedl - AI @pythonlbooks-📚 @programming_books_it -it 📚 № 5032728887

Subscribe to a channel

Java Books

Java-ловушка: почему `parallelStream()` может замедлить приложение

Многие думают:

«Есть stream(), добавлю parallelStream() — станет быстрее».

Но не всегда.

parallelStream() использует общий ForkJoinPool Java:


users.parallelStream()
.map(this::callExternalApi)
.toList();


Если внутри идут HTTP-запросы, SQL или ожидание внешнего сервиса, можно получить обратный эффект:

забить общий пул потоков
увеличить задержки
замедлить другие части приложения

parallelStream() хорошо подходит для:

✅ сложных CPU-вычислений
✅ обработки больших коллекций
✅ математических операций

Но плохо подходит для:

❌ HTTP
❌ базы данных
❌ файлового I/O
❌ ожидания внешних сервисов

Для таких задач лучше использовать отдельный пул:


ExecutorService executor =
Executors.newFixedThreadPool(20);


и контролировать количество параллельных операций.

Главное правило:

parallelStream() — для вычислений.
ExecutorService — для бизнес-логики и внешних вызовов.

Код может идеально работать на тестах, но в production внезапно получить проблемы из-за одного parallelStream().

Читать полностью…

Java Books

Полезный Java-совет:

Не вызывай parallelStream() просто потому, что данных много.

Для коротких операций он легко оказывается медленнее обычного stream(), потому что платишь за разбиение задачи, синхронизацию и работу ForkJoinPool.

Особенно неприятно то, что по умолчанию parallelStream() использует общий ForkJoinPool.commonPool(). Если приложение уже нагружает его другими задачами, производительность может внезапно просесть вообще в другом месте.

Если параллелизм реально нужен, лучше контролировать executor явно, а не прятать его внутри parallelStream().

Читать полностью…

Java Books

💻 Как прокачать фронтенд, бэкенд и зайти в разработку ИИ-систем

Современный веб-интерфейс на React, сложные архитектуры, асинхронность или сборка RAG-пайплайнов — все эти вещи требуют плотной практики. Если планируете расти в грейде, освоить новую профессию или менять стек, скоро завершается прием документов на двухлетнюю онлайн-магистратуру ИТМО в партнерстве с Яндекс Практикумом «Фронтенд-, бэкенд‑разработка и ИИ‑решения».

Учеба идет по вечерам, так что бросать текущую работу не придется. При этом сохраняются все бонусы очников, включая студенческие льготы.

Что ждет студентов:

— Разделение по уровням. Сетка из 9 треков на выбор: от старта с нуля на Java, Python, C++ или JS до хардовых программ для продвинутых. Там уже будут разбирать Spring Boot, Kafka, Cloud Native, C++ под Boost, NestJS и асинхронный бэкенд. 

— Отдельное направление «ИИ-решения в разработке». Оно заточено под проектирование LLM-систем, сборку RAG-пайплайнов и работу с мультиагентными сетями. 

— Практика, которой очень много. Сможете пополнить портфолио 10+ проектами, а еще будете решать реальные задачи от партнеров программы и команд Яндекса. 

— Применение AI с пользой. Научат отдавать нейросетям рутину: от дебага и рефакторинга до генерации тестов и документации.

Выпускники получают диплом магистра ИТМО и официальный диплом о профпереподготовке от Яндекса. Отбор проходит по вступительным испытаниям или по рекомендательному письму для выпускников Практикума. 

Узнать подробности. 

Читать полностью…

Java Books

Лето, ИТ-Пикник и музыка известных артистов уже через несколько дней!

8 августа в Коломенском пройдет ИТ-Пикник.

В программе — выступления проекта LAB Антона Беляева, IOWA, Cream Soda, Pompeya, мартина и Совы.

А днем — научпоп-лекции, дискуссии об ИИ и больших языковых моделях, мастер-классы и интерактивы. Полезные знакомства и развлечения тоже будут.

Зарегистрироваться и узнать подробности можно на сайте мероприятия.

В билет входит +1 — можно позвать близких и друзей.

До встречи в месте притяжения ИТ.

Читать полностью…

Java Books

Собираем бэкенд-комьюнити на JVM Day

Бэкендеры, 29 августа в Москве пройдет хардкорная конференция. Ждут своих: Java-, Scala- и Kotlin-разработчиков, архитекторов и тимлидов.

Здесь выступят и расскажут:
— Андрей Кулешов — что нового в мире JVM за год.
— Сергей Петрелевич — разработка по Mechanical Sympathy.
— Александр Ланцов — Java после Loom: другие модели concurrency.
— Антон Курако — как бенчмарки вводят в заблуждение.

А вечером во дворе T-Space — посиделки, интерактивы и открытый микрофон с историями ошибок.
Мест мало, а цена билета будет расти.

Успевай зарегистрироваться

Читать полностью…

Java Books

🖥 Java можно учить месяцами - и всё равно бояться написать собственный сервер

Курс «Java: с нуля до сетевого гуру» построен так, чтобы ты как можно быстрее перешёл от теории к рабочему коду.

Сначала разберёшь основы языка, ООП, коллекции и исключения. Затем перейдёшь к тому, ради чего многие и выбирают Java:

- многопоточность;
- TCP/IP и сокеты;
- клиент-серверные приложения;
- обработка нескольких подключений;
- собственные сетевые проекты.

Каждая новая тема закрепляется практикой. Ты будешь запускать серверы, подключать клиентов, передавать данные и постепенно собирать проекты, которые уже можно показывать в портфолио.

Курс подходит новичкам. Никакой подготовки не требуется: обучение начинается с базы и шаг за шагом выводит к задачам реальной backend-разработки.

В результате ты получишь крепкую основу Java, поймёшь, как работают сетевые приложения, и перестанешь смотреть на серверный код как на магию.

Начни сейчас - и преврати Java из «когда-нибудь выучу» в навык, которым уже можно пользоваться.

Курс доступен на Stepik: https://stepik.org/a/295392/

Читать полностью…

Java Books

Java-совет: два разных пути могут вести к одному файлу

Сравнение через Path.equals() проверяет только сами пути. Поэтому эти значения считаются разными:


Path path1 = Path.of("data/report.txt");
Path path2 = Path.of("data/../data/report.txt");


Чтобы проверить, указывают ли они на один и тот же реальный файл, используйте:


boolean same = Files.isSameFile(path1, path2);


Метод учитывает:

- относительные и абсолютные пути;
- символические ссылки;
- особенности файловой системы;
- разные способы записи одного расположения.

Пример:


Path original = Path.of("/app/config.json");
Path symlink = Path.of("/app/current-config");

if (Files.isSameFile(original, symlink)) {
System.out.println("Это один файл");
}


Важно: метод обращается к файловой системе и может выбросить IOException.

Files.isSameFile() полезен перед копированием, перемещением или удалением файлов — особенно когда в проекте используются символические ссылки и нестандартные пути.

Читать полностью…

Java Books

❓Что из вариантов лучше всего описывается определением: Операция, которая содержит серию задач, которые должны быть выполнены либо все, либо не выполнена ни одн

#spring

Читать полностью…

Java Books

Кто-то разобрал Claude Code почти до винтика

learn-coding-agent - репозиторий для тех, кто хочет понять, как устроены современные coding agents не на уровне промо-страниц, а на уровне архитектуры.

Автор собрал разбор Claude Code по публичным источникам: цикл агента, систему инструментов, разрешения, работу с контекстом, сессии, подпроцессы, MCP, удалённые настройки, телеметрию и скрытые флаги.

Получился не “гайд по использованию”, а карта внутренней логики CLI-агента: как он принимает решение, когда просит разрешение, как вызывает инструменты, как хранит историю и как расширяется через внешние интеграции.

https://github.com/justxor/Claudecourse/

Читать полностью…

Java Books

💡 Java: делегирование часто безопаснее наследования

Наследование кажется удобным, пока суперкласс не начинает жить своей жизнью.

Если класс наследуется от родителя, он получает весь его API. Любое изменение сверху может внезапно сломать поведение дочернего класса.

С делегированием проще: объект хранит внутри helper/service и передаёт ему нужные вызовы.

Плюсы:

* меньше жёсткой связности
* проще тестировать и мокать
* легче менять реализацию
* меньше риска сломаться из-за изменений в родителе

Правило простое: наследуйтесь только когда связь is-a действительно железная. В остальных случаях чаще лучше композиция и делегирование.

Читать полностью…

Java Books

Новая фича затрагивает десятки файлов? Тесты становятся сложнее самого кода? А когда бизнес меняет требования — приходится переписывать половину сервиса?

Если это знакомо, то проблема, скорее всего, не в коде.
🚫 Проблема в архитектуре.

🔥 15 июля стартует практический курс по Domain-Driven Design и Clean Architecture на Java.

За 6 недель вы научитесь:
✔️ Организовывать код так, чтобы новые требования не приводили к переписыванию половины сервиса
✔️ Изолировать бизнес-логику от HTTP, Kafka, БД и других технических деталей
✔️ Строить сервисы, которые проще поддерживать, тестировать и развивать
✔️ Писать тесты, которые проверяют поведение системы, а не набор моков
✔️ Добавлять новые интеграции без изменений в ядре приложения
✔️ Уверенно работать со сложной бизнес-логикой без постоянного роста технического долга

Для этого на практике разберёте Domain-Driven Design, Aggregate, Entity и Value Object, освоите Domain Events, Clean Architecture, Hexagonal и Onion Architecture.

📦 На курсе вы соберёте полноценный сервис диспетчеризации заказов и получите готовый шаблон микросервиса, который сможете использовать в рабочих проектах.

Автор курса — Кирилл Ветчинкин, архитектор Авито, ex Staff Engineer в Купер.

👉 Посмотрите первый модуль и оцените, насколько этот подход подходит для ваших проектов: https://microarch.ru/courses/ddd/languages/java?utm_source=posev&utm_medium=erid:2VtzqwyW4fK&utm_campaign=1

Реклама. ИП Ветчинкин К.Е. ИНН: 773376451099 Erid: 2VtzqwyW4fK

Читать полностью…

Java Books

✔️ Java-совет, который спасает от тихих утечек ресурсов.

Если работаете с BufferedReader, InputStream, OutputStream, FileReader, соединениями или другими ресурсами, которые нужно закрывать, используйте try-with-resources.

Плохо:


BufferedReader reader = new BufferedReader(new FileReader("data.txt"));

String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}

reader.close();


На первый взгляд всё нормально.

Но если внутри чтения файла вылетит исключение, reader.close() может не выполниться. В итоге останутся открытые file handles, stream’ы или соединения.

Лучше так:


try (BufferedReader reader =
new BufferedReader(new FileReader("data.txt"))) {

String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}


try-with-resources автоматически вызовет close() даже при исключении.

Почему это важно:

* не нужен ручной finally
* меньше boilerplate-кода
* ниже риск утечек ресурсов
* код проще читать
* безопаснее работать с файлами, сетью и БД

Правило простое:

если объект реализует AutoCloseable или Closeable, почти всегда стоит использовать try-with-resources.

Это одна из тех привычек, которые делают Java-код чище и надёжнее.

Читать полностью…

Java Books

N+1 в Spring Boot выглядит безобидно, пока прод не начинает молиться на базу данных.

Классический сценарий:

Вы грузите список заказов:

orderRepository.findAll()

А потом в цикле обращаетесь к order.getItems().

Hibernate сначала делает один запрос за заказами, а потом ещё по одному запросу на каждый заказ, чтобы достать items.

100 заказов = 101 SQL-запрос.

И вот здесь спасает @EntityGraph.

Он позволяет явно сказать репозиторию, какие связи нужно подтянуть сразу:

@EntityGraph(attributePaths = {"items"})

В итоге Hibernate может сгенерировать один запрос с JOIN, вместо десятков лишних походов в базу.

Что получаем:

- меньше SQL-запросов
- меньше нагрузки на БД
- чище код репозитория
- без ручного JPQL
- fetch-стратегия управляется точечно под конкретный кейс

LAZY сам по себе не зло. Зло - когда вы не контролируете, где и как он срабатывает.

@EntityGraph - один из самых простых способов держать N+1 под контролем в Spring Boot.

Читать полностью…

Java Books

Spring Boot: уберите try/catch из контроллеров

В Spring Boot не нужно размазывать обработку ошибок по каждому endpoint через бесконечные try/catch.

Для этого есть @RestControllerAdvice.

Идея простая: вы выносите обработку исключений в один глобальный класс, а контроллеры оставляете чистыми.

Например:


@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse("NOT_FOUND", ex.getMessage()));
}

@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<?> handleBadRequest(IllegalArgumentException ex) {
return ResponseEntity
.badRequest()
.body(new ErrorResponse("BAD_REQUEST", ex.getMessage()));
}

@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleGeneric(Exception ex) {
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ErrorResponse("INTERNAL_ERROR", "Something went wrong"));
}
}


После этого контроллер может выглядеть спокойно:


@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}


Если пользователь не найден - сервис кидает ResourceNotFoundException, а Spring сам отправит нормальный 404.

Что это даёт:

• меньше мусора в контроллерах
• единый формат ошибок
• проще поддерживать API
• легче логировать исключения
• меньше копипасты в endpoint-ах

Контроллер должен описывать сценарий запроса, а не превращаться в свалку обработки ошибок.

Читать полностью…

Java Books

Небольшой, но полезный совет для Spring Boot.

Если у вас есть scheduled task, не стоит хардкодить интервал прямо в аннотации:


`@Scheduled(fixedRate = 5000)`


Лучше вынести значение в конфиг:


`@Scheduled(fixedRateString = "${task.interval}")`


А в application.properties указать:


`task.interval=5000`


Почему так лучше:

• интервал можно менять без правки кода;
• настройки проще различать для dev, staging и production;
• меньше магических чисел в бизнес-логике;
• конфигурация становится прозрачнее.

Мелочь, но именно из таких мелочей и складывается нормальная поддерживаемость Spring Boot-проекта.

Читать полностью…

Java Books

Вам доклады по Go или Java? VK приглашает на митап с двойной начинкой
26 августа VK собирает Go- и Java-инженеров, чтобы прокачать знания.

В программе два трека — Go и Java, по три доклада в каждом.

Трек Go:
• «Компиляция Go в динамическую либу, или как мы ускорили выкатку фичи в два раза, но нам не понравилось», Михаил Кичигин, бэкенд-разработчик, Avito Tech
• «Go-платформа VK: как мы построили единую основу для создания Go-сервисов», Александр Апанасенко, руководитель команды SDK Backend, VK
• «Почтальон от Kubernetes до Palo Alto. Как осуществляется доставка информации об адресах», Дарья Кулькина, бэкенд-разработчик, Точка Банк

Трек Java:
• «Перформанс-трюки в поисковой платформе Ozon», Пётр Портнов, ведущий разработчик среднего поиска, Ozon
• «Архитектура современного движка платёжной системы и переход к новой архитектуре», Игорь Крикунов, технический лидер разработки DBC, Альфа-Банк
• «Переход от федерации S3-кластеров в пользу коммунального и мультитенантного кластера», Кирилл Боблак, ведущий разработчик One-cloud, VK

А ещё будет мастер-класс по прокачке навыка, который сделает вас звездой любого вечера, и афтепати, чтобы обсудить доклады в неформальной обстановке.

Встречаемся в 17:00, начало в 18:00. Участие бесплатное, регистрация обязательна.

Читать полностью…

Java Books

⚡️ Java-приём: не храни метаданные классов в `static Map<Class<?>, ...>` — используй `ClassValue`.

Допустим, библиотека кеширует информацию о каждом классе:


private static final Map<Class<?>, Metadata> CACHE =
new ConcurrentHashMap<>();


На первый взгляд всё нормально.

Но в приложениях с динамической загрузкой классов — plugins, application servers, hot reload — такой кеш может удерживать Class, а вместе с ним и его ClassLoader.

И получить неприятную утечку памяти.

В Java для этого есть малоизвестный ClassValue<T>:


private static final ClassValue<Metadata> CACHE =
new ClassValue<>() {
@Override
protected Metadata computeValue(Class<?> type) {
return buildMetadata(type);
}
};


Использование:


Metadata metadata = CACHE.get(MyClass.class);


Что даёт ClassValue:

- ленивое вычисление значения для каждого класса;
- thread-safe доступ;
- не нужен собственный ConcurrentHashMap;
- кеш лучше согласован с жизненным циклом загруженных классов.

Особенно полезно для reflection, serializers, ORM, DI-контейнеров и framework-кода, где постоянно кешируются данные по Class<?>.

🔥 Если видишь в библиотеке:


static ConcurrentHashMap<Class<?>, ...>


стоит хотя бы задать вопрос:

а почему здесь не `ClassValue`?

#Java #JVM #Backend #Programming

Читать полностью…

Java Books

☕️ Java-совет: не запускайте блокирующий I/O через `CompletableFuture` без собственного пула

Такой код выглядит асинхронным:


CompletableFuture<User> future =
CompletableFuture.supplyAsync(() -> userClient.loadUser(id));


Но без явного Executor задача обычно попадёт в общий ForkJoinPool.commonPool().

Если loadUser() ждёт HTTP, базу данных или файловую систему, поток блокируется. Несколько медленных вызовов могут занять весь общий пул и затормозить совершенно несвязанные операции приложения.

Лучше выделить отдельный пул для блокирующего I/O:


private static final ExecutorService IO_POOL =
Executors.newFixedThreadPool(32);

CompletableFuture<User> future =
CompletableFuture.supplyAsync(
() -> userClient.loadUser(id),
IO_POOL
);


И не забыть корректно его закрыть:


IO_POOL.shutdown();


Для цепочки тоже важно явно выбирать executor:


future.thenApplyAsync(
user -> enrichUser(user),
IO_POOL
);


Почему это полезно:

- медленный внешний сервис не блокирует общий пул;
- нагрузку можно ограничить размером executor;
- проще наблюдать очередь и время выполнения;
- разные типы задач не мешают друг другу.

CompletableFuture не делает блокирующий код неблокирующим. Он лишь переносит ожидание в другой поток.

Асинхронность без контроля executor - это просто блокировка в менее заметном месте.

Читать полностью…

Java Books

💡 Java совет: два пути могут указывать на один и тот же файл

Path.equals() сравнивает только представление пути:


Path a = Path.of("data.txt");
Path b = Path.of("./data.txt");

System.out.println(a.equals(b)); // false


Хотя оба пути могут вести к одному файлу.

Для проверки используйте:


boolean same = Files.isSameFile(a, b);


Files.isSameFile() обращается к файловой системе и учитывает:

- относительные пути;
- символические ссылки;
- реальное расположение файла.


Path file = Path.of("data.txt");
Path link = Path.of("data-link.txt");

Files.isSameFile(file, link); // true, если link ведёт к data.txt


Полезно при поиске дубликатов, проверке пользовательских путей и защите от повторной обработки одного файла.

Учтите: метод может обращаться к диску и выбрасывать IOException, поэтому это не просто строковое сравнение.

Доступно начиная с Java 7.

#Java #JavaTips #Files

Читать полностью…

Java Books

💡 Java cj: unmodifiableList() не делает настоящую копию

Эти два варианта выглядят похоже, но работают по-разному:


List<String> source = new ArrayList<>();
source.add("Java");

List<String> view = Collections.unmodifiableList(source);
List<String> copy = List.copyOf(source);

source.add("Spring");

System.out.println(view); // [Java, Spring]
System.out.println(copy); // [Java]


Collections.unmodifiableList() создаёт только неизменяемое представление исходного списка. Если source изменится, изменения появятся и в view.

List.copyOf() создаёт отдельный неизменяемый снимок данных.

Используйте:

- unmodifiableList() — когда нужен read-only view актуального списка;
- List.copyOf() — когда нужно зафиксировать состояние и безопасно вернуть его наружу.


public List<String> getUsers() {
return List.copyOf(users);
}


Так внешний код не сможет изменить внутреннюю коллекцию, а последующие изменения users не повлияют на уже возвращённый результат.

List.copyOf() доступен начиная с Java 10.

#Java #JavaTips #Backend

Читать полностью…

Java Books

💡 Редкий совет Java: используйте `ClassValue` для кэша, привязанного к классу

Обычно метаданные кэшируют так:

Map<Class<?>, Metadata> cache = new ConcurrentHashMap<>();

Но такой кэш способен удерживать классы и их ClassLoader, создавая утечки памяти в плагинах, серверах приложений и системах с динамической загрузкой.

Для подобных случаев в Java есть ClassValue:

private static final ClassValue<Metadata> CACHE =
new ClassValue<>() {
@Override
protected Metadata computeValue(Class<?> type) {
return inspect(type);
}
};

Metadata metadata = CACHE.get(User.class);

Значение вычисляется отдельно для каждого класса и может быть очищено после его выгрузки.

ClassValue особенно полезен для reflection-кэшей, сериализаторов, ORM, прокси и плагинных архитектур.

Редкий инструмент JVM, который часто безопаснее, чем ConcurrentHashMap<Class<?>, ...>.

#Java #JVM #Backend #Performance

Читать полностью…

Java Books

Rust, который наконец становится понятным 🦀

Давно хочешь выучить Rust, но ownership, borrowing и lifetimes выглядят как отдельный вид боли?

Этот курс проведёт тебя с самого начала до уровня, где ты уже пишешь реальные системные и сетевые программы.

Ты разберёшь:
Ownership → Borrowing → ошибки → коллекции → Generics → Traits → модули → тесты → сетевой код

Никакого бесконечного чтения документации. После каждого урока ты сразу пишешь код, проходишь тесты и решаешь задачу с автопроверкой.

🔥 Rust с нуля
🔥 5–6 часов в неделю
🔥 Практика после каждого урока
🔥 Подойдёт после Python, JavaScript, Java и других языков
🔥 Можно начать сразу

В конце у тебя будет понимание Rust, с которым уже можно писать быстрые backend-сервисы, сетевые приложения и системные утилиты, а не смотреть на borrow checker как на врага.

Пора добавить Rust в свой стек. Начинай курс и пиши первый код уже сегодня: https://stepik.org/a/294885/

Читать полностью…

Java Books

🔥 Хочешь быстрее расти в IT? Хватит учиться в одиночку

В IT прокачивается тот, кто каждый день видит сильные идеи, новые инструменты, реальные задачи, вакансии и разборы.

Окружение решает больше, чем кажется.

Собрал папки и каналы, где можно быстрее влиться в нужное направление, следить за трендами и не вариться в своём пузыре.

AI: t.me/ai_machinelearning_big_data
Python: t.me/pythonl
Linux: t.me/linuxacademiya
Хакинг: t.me/linuxkalii
DevOps: t.me/DevOPSitsec
Docker: t.me/DevopsDocker
Golang: t.me/Golang_google
Rust: t.me/rust_code
C++: t.me/cpluspluc
C#: t.me/csharp_1001_notes
Java: t.me/java_library
JavaScript: t.me/javascriptv
React: t.me/react_tg
Frontend: t.me/front
PHP: t.me/phpshka
Android: t.me/android_its
Мобильная разработка: t.me/mobdevelop
Базы данных: t.me/sqlhub
Data Science: t.me/data_analysis_ml
Big Data: t.me/bigdatai
Математика: t.me/data_math
Физика: t.me/fizmat
Kubernetes: t.me/kubernetc
GameDev: /channel/gamedev
Haskell: t.me/haskell_tg

Собеседования и карьера:

DS собеседования: t.me/machinelearning_interview
Python собеседования: t.me/python_job_interview

Папка с вакансиями: t.me/addlist/_zyy_jQ_QUsyM2Vi
Папка Go разработчика: t.me/addlist/MUtJEeJSxeY2YTFi
Папка Python разработчика: t.me/addlist/eEPya-HF6mkxMGIy
Папка ML: /channel/addlist/2Ls-snqEeytkMDgy
Папка Frontend: /channel/addlist/mzMMG3RPZhY2M2Iy

Полезное сверху:

ИТ-мемы: t.me/memes_prog
Английский для программистов: t.me/english_forprogrammers
ИИ и технологии: t.me/vistehno
954 ГБ open-source курсов: @courses
ИТ-книги бесплатно: /channel/addlist/BkskQciUW_FhNjEy

Max Ai: https://max.ru/ai_machinelearning_big_data
Max python: https://max.ru/pythonl
ТЕХНО: https://max.ru/vistehno
Max Go: https://max.ru/Golang_google
Max Linux: https://max.ru/linuxkalii
Devops: https://max.ru/DevOPSitsec
C#: https://max.ru/csharp_ci
C++: https://max.ru/cpluspluc
SQL: https://max.ru/sqlhub
Java: https://max.ru/javatg

Подписывайся на нужные направления и собирай себе ленту, которая реально двигает вперёд.

Пока кто-то листает шум, ты будешь видеть инструменты, задачи и идеи, которые помогают расти в профессии.

Читать полностью…

Java Books

Если хочешь развиваться в бэкенд-разработке — выстроить сильную базу, углубиться в архитектуру или перейти в роль тимлида — в Центральном университете есть магистратура под каждый сценарий. И на нее можно получить грант до 75%. Места ограничены, дедлайн подачи заявок — 20 августа.

«Бэкенд-разработка» — это офлайн-направление (пары по вечерам и в выходные в центре Москвы) с тремя треками на выбор:
⚫️Технический — для студентов старших курсов и разработчиков в начале карьеры. Языки программирования, DevOps-инструменты, базы данных, архитектура ПО и распределенные системы. Программа ежегодно обновляется под реальные запросы компаний, а преподают разработчики, тимлиды и CTO из ведущих IT-компаний. К выпуску — сильное портфолио бэкенд-проектов
⚫️Совместный с MAGNIT TECH — обучение на реальных кейсах и архитектуре распределенных систем федерального масштаба, буткемп с экспертами компании и возможность выйти на оплачиваемую стажировку в техническую команду в течение первого года
⚫️Тимлидский — для опытных разработчиков, которые хотят перейти к роли руководителя команды: выстраивать процессы разработки, принимать архитектурные решения и развивать команду

Магистратура в Центральном университете — это 2 года обучения, которое можно совмещать с работой, и диплом государственного образца. Карьерная поддержка начинается еще во время учебы: консультации, тренировочные собеседования и помощь с трудоустройством. Студенты уже в процессе обучения выходят на новые позиции или повышаются в грейде в Яндексе, Авито, Т-Банке и других компаниях.

Поступление проходит через грантовый конкурс — это одновременно способ попасть на программу и возможность выиграть финансовую поддержку на все время обучения: грант покрывает до 75% стоимости. В 2026 году доступно 550 грантов на все программы магистратуры.

Подробнее о программе и условиях участия в конкурсе — по ссылке

Читать полностью…

Java Books

N+1 в Spring Boot выглядит безобидно, пока прод не начинает молиться на базу данных.

Классический сценарий:

Вы грузите список заказов:

orderRepository.findAll()

А потом в цикле обращаетесь к order.getItems().

Hibernate сначала делает один запрос за заказами, а потом ещё по одному запросу на каждый заказ, чтобы достать items.

100 заказов = 101 SQL-запрос.

И вот здесь спасает @EntityGraph.

Он позволяет явно сказать репозиторию, какие связи нужно подтянуть сразу:

@EntityGraph(attributePaths = {"items"})

В итоге Hibernate может сгенерировать один запрос с JOIN, вместо десятков лишних походов в базу.

Что получаем:

- меньше SQL-запросов
- меньше нагрузки на БД
- чище код репозитория
- без ручного JPQL
- fetch-стратегия управляется точечно под конкретный кейс

LAZY сам по себе не зло. Зло - когда вы не контролируете, где и как он срабатывает.

@EntityGraph - один из самых простых способов держать N+1 под контролем в Spring Boot.

Читать полностью…

Java Books

🖥 В Java длинные цепочки вроде `user → address → city` легко превращаются в ловушку для `NullPointerException`.

Обычный вариант быстро разрастается:


User user = userRepository.findByEmail(email);

if (user != null) {
Address address = user.getAddress();

if (address != null) {
return address.getCity();
}
}

return "unknown";


Проблема не только в количестве строк.

В таких вложенных if легко забыть один уровень проверки и получить NPE в самом неожиданном месте.

С Optional это можно записать короче и безопаснее:


return userRepository.findByEmail(email)
.map(User::getAddress)
.map(Address::getCity)
.orElse("unknown");


Каждый map() выполняется только если предыдущее значение существует.

Если пользователя нет, адреса нет или город не задан - цепочка спокойно дойдёт до orElse().

Для таких случаев Optional хорошо работает как способ явно показать:

значение может отсутствовать, и это нормальная часть логики.

Главное не превращать Optional в новую религию.

Он особенно полезен на границах методов и в цепочках, где каждый следующий шаг может вернуть null.

Читать полностью…

Java Books

📌 Magic numbers в Java - мелкая привычка, которая потом превращает поддержку кода в археологию.

Когда в коде встречается 86400, 7, 1.21 или 5000, компилятору всё равно. Человеку - нет. Через месяц уже приходится вспоминать, что это было: секунд в дне, дней сессии, НДС или задержка перед повторной попыткой.

Плохой вариант выглядит так:

if (sessionAgeSeconds > 86400 * 7)

Формально код работает. Но смысл спрятан внутри чисел.

Нормальный вариант:

SECONDS_PER_DAY
SESSION_DAYS
VAT_RATE
RETRY_DELAY_MS

Теперь намерение видно прямо в месте вызова. Не нужно угадывать, почему именно 7, что означает 5000 и можно ли безопасно поменять значение.

Это особенно важно в бизнес-логике, где числа редко бывают случайными. Лимиты, комиссии, таймауты, скидки, сроки жизни сессии, количество попыток - всё это правила продукта, а не просто цифры в коде.

Хорошее правило простое: если число несёт смысл, дай ему имя. Исключения вроде 0, 1, индексов и простых счётчиков можно не трогать.

Чистый код часто начинается не с архитектуры, а с таких скучных вещей: убрать загадочные числа и оставить будущему разработчику понятный контекст.

#java #cleancode

Читать полностью…

Java Books

Твой код — в сердце мощного ИИ! 💚

Команда GigaChat зовёт на One Day Offer амбициозных Java-разработчиков, которые готовы создавать AI‑продукты уровня BigTech и стать частью крупнейшего AI-комьюнити.

Если ты дружишь с Java (версии 8–25), ладишь со Spring и Hibernate, а PostgreSQL и ClickHouse для тебя — не просто слова, переходи по ссылке и занимай слот на One Day Offer.

Встречаемся 23 мая — очень ждём именно тебя!

Читать полностью…

Java Books

N+1 в Spring Boot выглядит безобидно, пока прод не начинает молиться на базу данных.

Классический сценарий:

Вы грузите список заказов:

orderRepository.findAll()

А потом в цикле обращаетесь к order.getItems().

Hibernate сначала делает один запрос за заказами, а потом ещё по одному запросу на каждый заказ, чтобы достать items.

100 заказов = 101 SQL-запрос.

И вот здесь спасает @EntityGraph.

Он позволяет явно сказать репозиторию, какие связи нужно подтянуть сразу:

@EntityGraph(attributePaths = {"items"})

В итоге Hibernate может сгенерировать один запрос с JOIN, вместо десятков лишних походов в базу.

Что получаем:

- меньше SQL-запросов
- меньше нагрузки на БД
- чище код репозитория
- без ручного JPQL
- fetch-стратегия управляется точечно под конкретный кейс

LAZY сам по себе не зло. Зло - когда вы не контролируете, где и как он срабатывает.

@EntityGraph - один из самых простых способов держать N+1 под контролем в Spring Boot.

Читать полностью…

Java Books

⚡️ CORS в Spring Boot: не лечите это костылями на фронте

Если frontend и backend живут на разных доменах или портах, браузер начнет резать запросы по CORS. Это не баг Spring Boot и не проблема React. Это нормальный механизм безопасности браузера.

Правильный способ - настроить CORS на стороне backend.

В Spring Boot это можно сделать глобально через WebMvcConfigurer: указать маршруты, разрешенные origins, HTTP-методы, заголовки и работу с credentials.

Главное - не ставить бездумно * везде подряд, особенно если используете cookies, токены или allowCredentials(true). В проде лучше явно перечислять доверенные домены, например frontend-домен приложения.

Такой подход дает централизованный контроль: вы один раз задаете политику CORS и не размазываете настройки по каждому контроллеру.

Для Java backend-разработчика это базовая, но важная вещь: CORS должен быть частью архитектуры API, а не случайной правкой перед деплоем.

Читать полностью…
Subscribe to a channel