fa
Feedback

فریب کلاهبرداران را نخورید! تل‌متریو این کانال‌ها را شناسایی و برچسب‌گذاری می‌کند 👉 برای مشاهده برچسب، اشتراک تهیه کنید

Библиотека Java разработчика

Библиотека Java разработчика

رفتن به کانال در Telegram

📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP

نمایش بیشتر
9 998
مشترکین
-324 ساعت
-47 روز
-5930 روز
آرشیو پست ها
🚀 Оптимизация SQL-запросов в Java: используем Query Hints правильно! Сегодня я хочу поговорить о Query Hints – мощном, но часто игнорируемом инструменте, который может значительно ускорить SQL-запросы в Java-приложениях. 🔥 Что такое Query Hints? Query Hints – это специальные инструкции для базы данных, которые помогают оптимизатору запросов выбрать наиболее эффективный план выполнения. В Java (Hibernate, JPA, Spring Data) их можно использовать для управления кешированием, выбором индексов и стратегией выполнения. ⚡ Как использовать Query Hints в Hibernate? В Hibernate есть два способа добавления Query Hints: 1. Через EntityManager

Query query = entityManager.createQuery("SELECT u FROM User u WHERE u.age > :age")
        .setParameter("age", 25)
        .setHint("org.hibernate.cacheable", true);
List<User> users = query.getResultList();
Здесь "org.hibernate.cacheable" позволяет кешировать результат запроса. 2. Аннотация @QueryHint (Spring Data JPA)

@QueryHints({@QueryHint(name = "org.hibernate.readOnly", value = "true")})
@Query("SELECT u FROM User u WHERE u.status = 'ACTIVE'")
List<User> findActiveUsers();
Этот hint указывает Hibernate, что данные только для чтения, что может ускорить выполнение. 🔍 Полезные Query Hints Вот несколько полезных хинтов для Hibernate: - org.hibernate.cacheable = true – разрешает кеширование результата. - org.hibernate.fetchSize = N – задаёт количество строк, загружаемых за раз. - org.hibernate.readOnly = true – отключает слежение за изменениями (ускоряет SELECT). - org.hibernate.comment = 'My custom hint' – добавляет комментарий к запросу. ❗ Когда использовать? ✅ При сложных JOIN-запросах ✅ При работе с кешем ✅ Для больших выборок (fetchSize) ✅ Если запрос не изменяет данные (readOnly) А вы используете Query Hints в своих проектах? Делись в комментариях! 👇 👉@BookJava

👩‍💻 Открытый урок «Spring Boot: разбор (не)стандартных вопросов интервью» 🗓 17 марта в 20:00 МСК 🆓 Бесплатно. Урок в рамк
👩‍💻 Открытый урок «Spring Boot: разбор (не)стандартных вопросов интервью» 🗓 17 марта в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта курса «Разработчик на Spring Framework» Продолжаем готовится к возможному собеседованию. На уроке мы обсудим вопросы, которые могут встретиться на интервью по теме разработки на Spring. На очереди Spring Boot. Подключайтесь. 🔗 Ссылка на регистрацию: https://vk.cc/cJBl4X Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

🔥 Stream API: Фильтрация, Преобразование и Сортировка 🔥 Сегодня я покажу вам, как эффективно работать с Stream API в Java, выполняя фильтрацию, преобразование и сортировку данных. Допустим, у нас есть список пользователей:

class User {
    String name;
    int age;

    User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}
Теперь представьте, что у нас есть список пользователей, и мы хотим: ✅ Оставить только совершеннолетних ✅ Отсортировать их по возрасту ✅ Преобразовать в список имен Легко справимся с этим с помощью Stream API:

List<User> users = List.of(
    new User("Алекс", 25),
    new User("Мария", 17),
    new User("Иван", 30),
    new User("Ольга", 20)
);

List<String> adultNames = users.stream()
    .filter(user -> user.age >= 18)  // Фильтрация
    .sorted(Comparator.comparingInt(user -> user.age)) // Сортировка
    .map(user -> user.name) // Преобразование
    .toList();

System.out.println(adultNames); // [Ольга, Алекс, Иван]
Что здесь происходит? 🔹 filter(user -> user.age >= 18): Убираем несовершеннолетних. 🔹 sorted(Comparator.comparingInt(user -> user.age)): Сортируем по возрасту. 🔹 map(user -> user.name): Преобразуем User в String, оставляя только имена. 🔹 toList(): Собираем результат в список. Stream API позволяет писать чистый, читаемый и декларативный код, избавляя от лишних циклов. А вы активно используете Stream API в своих проектах? Делитесь в комментариях! 🚀 👉@BookJava

🚀 Пишем эффективные SQL-запросы в Hibernate: ТОП ошибок и их исправление Сегодня поговорим о распространенных ошибках при работе с Hibernate и SQL-запросами. Многие из них приводят к проблемам с производительностью, искаженными данными и даже утечкам памяти. ❌ Ошибка №1: Избыточные запросы (N+1 Problem) _Проблема:_ Если загружать список сущностей и затем получать связанные данные в цикле, Hibernate будет делать отдельный SQL-запрос для каждой записи. _Пример:_

List<User> users = session.createQuery("FROM User", User.class).getResultList();
for (User user : users) {
    System.out.println(user.getOrders().size()); // Генерирует N дополнительных запросов!
}
✅ Решение: Используйте JOIN FETCH для загрузки связанных данных одним запросом:

List<User> users = session.createQuery(
    "SELECT u FROM User u JOIN FETCH u.orders", User.class).getResultList();
❌ Ошибка №2: Использование LIKE без индексов _Проблема:_ Запросы вида LIKE '%value%' приводят к полному сканированию таблицы, что критично для больших баз данных. _Пример:_

SELECT * FROM users WHERE username LIKE '%john%';
✅ Решение: 1. Используйте полнотекстовый поиск (например, PostgreSQL full-text search или **Elasticsearch**). 2. Если всё же нужен LIKE, постарайтесь использовать его в виде value%, чтобы индексы работали. ❌ Ошибка №3: Неиспользование batch_size для @OneToMany _Проблема:_ Если у вас коллекция @OneToMany, Hibernate может загружать каждый элемент отдельным запросом. ✅ Решение: Включаем batch_size, чтобы загружать данные пакетами:

@OneToMany(mappedBy = "user")
@BatchSize(size = 10)
private List<Order> orders;
Либо добавляем глобально в hibernate.cfg.xml:

<property name="hibernate.default_batch_fetch_size">10</property>
❌ Ошибка №4: Неограниченный размер выборки (LIMIT отсутствует) _Проблема:_ Запрос без LIMIT может возвращать тысячи строк, нагружая базу и приложение. ✅ Решение: Всегда указываем LIMIT или используем setMaxResults():

Query<User> query = session.createQuery("FROM User", User.class);
query.setMaxResults(50); // Ограничиваем выборку
List<User> users = query.getResultList();
🏆 Вывод Проблемы с Hibernate и SQL встречаются часто, но их можно легко избежать! Следите за запросами и используйте JOIN FETCH, индексы, batch_size и LIMIT, чтобы повысить производительность. А какие проблемы с Hibernate встречались вам? Делитесь в комментариях! 👇 👉@BookJava

⚡️ Квиз на знание Java Пройти тестирование — сложно! А ты справишься? 21 вопрос, 30 минут Проверь себя - пройди квиз и оцени
⚡️ Квиз на знание Java Пройти тестирование — сложно! А ты справишься? 21 вопрос, 30 минут Проверь себя - пройди квиз и оцени свой уровень навыков, а также свою готовность к обучению на курсе — «Разработчик на Spring Framework» от OTUS. 💻 За 5 месяцев обучения ты освоишь современные возможности Spring, научишься быстро проходить путь от идеи до production-grade, создавать Web-приложения на микросервисной архитектуре и решать высокоуровневые задачи по разработке. 👉 ПРОЙТИ ТЕСТ: https://vk.cc/cJotoa Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

📌 Spring Boot: Как использовать @Async и не напороться на проблемы? Сегодня я расскажу вам, как правильно использовать аннотацию @Async в Spring Boot, чтобы асинхронные задачи работали стабильно и без неожиданностей. 🔹 Что делает @Async? Эта аннотация позволяет выполнять методы в отдельном потоке, не блокируя основной поток приложения. Это удобно, когда нужно, например, отправить email или выполнить сложный расчет без задержки ответа пользователю. 🔹 Как правильно использовать? 1️⃣ Включите поддержку асинхронности Добавьте в главный класс Spring Boot: @EnableAsync @SpringBootApplication public class MyApplication { } 2️⃣ Аннотируйте метод в сервисе @Service public class EmailService { @Async public void sendEmail(String email) { System.out.println("Отправка email: " + email + " в потоке " + Thread.currentThread().getName()); } } 3️⃣ Вызывайте метод асинхронно @Component public class NotificationSender { private final EmailService emailService; public NotificationSender(EmailService emailService) { this.emailService = emailService; } public void notifyUser(String email) { emailService.sendEmail(email); System.out.println("Метод notifyUser выполняется в потоке " + Thread.currentThread().getName()); } } 🔹 Частые ошибки и их решения ❌ Вызываете асинхронный метод внутри того же класса? Spring не будет проксировать вызов, и @Async просто не сработает. Выносите метод в отдельный бин! ❌ Нет пула потоков? По умолчанию Spring использует SimpleAsyncTaskExecutor, который создает новый поток для каждой задачи. Это может перегрузить систему. Лучше явно указать пул: @Configuration @EnableAsync public class AsyncConfig { @Bean public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); executor.initialize(); return executor; } } 💡 Вы используете @Async в своем проекте? Какие были подводные камни? Делитесь в комментариях! 👉@BookJava

⚖️ 👩‍💻 Сравнение механизмов синхронизации потоков с помощью JMH Понимание синхронизации — ключ к многопоточности. Оцените э
⚖️ 👩‍💻 Сравнение механизмов синхронизации потоков с помощью JMH Понимание синхронизации — ключ к многопоточности. Оцените эффективность механизмов и проверьте гипотезы с помощью JMH. 🗓 13 марта в 20:00 МСК 🆓 Бесплатно. Урок в рамках старта курса «Java Developer. Advanced». 📌О чём поговорим: - Ключевые механизмы синхронизации в Java (synchronized, ReentrantLock и другие). - Особенности их применения в многопоточном коде и влияние на производительность. - Настройка и проведение бенчмарков JMH для объективного сравнения различных подходов. 📌Кому будет интересно: Java-разработчикам, инженерам по производительности и любителям многопоточности, желающим оценить скорость и надёжность разных механизмов. 📌В результате урока вы получите: - Навык реализации JMH-бенчмарков для сравнения различных инструментов синхронизации. - Понимание разницы в скорости работы механизмов и уверенность в выборе оптимального решения. 🔗 Ссылка на регистрацию: https://vk.cc/cJlnn7 Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Совет по Spring Boot 💡 Если вы используете DTO в Spring Data/JPA, вы можете автоматизировать отображение между сущностями и
Совет по Spring Boot 💡 Если вы используете DTO в Spring Data/JPA, вы можете автоматизировать отображение между сущностями и DTO с помощью библиотеки Blaze Persistence (https://persistence.blazebit.com). Тогда вы сможете воспользоваться преимуществами, например, паттерна Spring repository. 👉@BookJava

🏆 5 ЗОЛОТЫХ ПРАВИЛ ЧИСТОГО КОДА В JAVA 1️⃣ Понятные названия Используйте осмысленные имена для переменных, методов и классов. Название должно отвечать на вопрос "Что делает этот код?" без необходимости заглядывать внутрь. ❌ int a = 5; ✅ int maxRetries = 5; 2️⃣ Короткие методы Огромные методы с кучей логики сложно читать и поддерживать. Разбивайте их на мелкие, понятные части. Хороший метод делает только одну вещь и делает её хорошо. 3️⃣ Минимум вложенности Чем больше if-else и циклов внутри друг друга — тем сложнее понимать код. Используйте ранний выход (return, continue, break), чтобы уменьшить вложенность. 4️⃣ Избегайте магических чисел Никогда не вставляйте числа или строки прямо в код. Заводите константы. ❌ if (status == 3) {...} ✅ if (status == ORDER_COMPLETED) {...} 5️⃣ Отказ от комментариев в пользу читаемого кода Комментарий не должен объяснять что делает код — это обязанность самого кода! Если без комментариев неясно, что происходит, значит, нужно переписать код. 👉 Какое из этих правил вы чаще всего нарушаете? Или, может, у вас есть своё золотое правило чистого кода? Пишите в комментариях! 👉@BookJava

⁉️ По-прежнему перебираете списки с for и while? Код превращается в кашу из циклов и условий? Оптимизация занимает больше вре
⁉️ По-прежнему перебираете списки с for и while? Код превращается в кашу из циклов и условий? Оптимизация занимает больше времени, чем сам проект? 👩‍💻 Stream API — мощный инструмент, который позволит вам писать элегантный, лаконичный и производительный код. ⚡️ На открытом вебинаре 13 марта в 20:00 мск разберём ключевые операции Stream API, научимся фильтровать, группировать и трансформировать данные в несколько строк кода. 🎙 Спикер Александр Фисунов — Senior Kotlin Developer в SSP Software на проекте ВТБ, опытный Java-разработчик и кандидат технических наук. Участники вебинара получат скидку для обучение на курсе «Java-разработчик» 🔗 Ссылка на регистрацию: https://vk.cc/cJjAao Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

🔥 Почему Optional в Java – не просто контейнер! Сегодня разберём важную тему: Optional в Java – это не просто удобный способ избежать null, но и мощный инструмент для работы с потоками данных. 🚀 Как правильно использовать Optional? 1️⃣ Избегаем null-чеков Раньше код был полон if (obj != null), но теперь:

Optional<String> name = Optional.ofNullable(user.getName());
name.ifPresent(System.out::println);
Это делает код чище и понятнее. 2️⃣ Комбинируем с map() и flatMap() Если у нас есть объект, внутри которого другой объект, а внутри него – ещё один, Optional поможет избежать вложенных if-else:

Optional<String> city = Optional.ofNullable(user)
    .map(User::getAddress)
    .map(Address::getCity);
Всё элегантно и лаконично! 3️⃣ Используем orElse() и orElseGet() правильно ❌ Антипаттерн – всегда выполняет new Object():

User user = optionalUser.orElse(new User());
✅ Лучше так – orElseGet() вызовется только если optionalUser пуст:

User user = optionalUser.orElseGet(User::new);
Это особенно важно, если объект тяжёлый в создании. 4️⃣ orElseThrow() – избавляемся от null вообще Когда отсутствие значения – это ошибка, не бойтесь выбрасывать исключение:

User user = optionalUser.orElseThrow(() -> new RuntimeException("User not found"));
Это делает код безопаснее! ❌ Когда не стоит использовать Optional? - В полях сущностей (например, JPA) – это может ухудшить производительность. - Для коллекций – лучше возвращать пустую коллекцию, а не Optional<List<T>>. А как ты используешь Optional в своём коде? Делись в комментариях! 👇 👉@BookJava

🔍Что спрашивают на собеседовании у Middle Java-разработчика❔ Уже завтра, 5 марта в 19:00 мск — бесплатное открытое собеседов
🔍Что спрашивают на собеседовании у Middle Java-разработчика❔ Уже завтра, 5 марта в 19:00 мск — бесплатное открытое собеседование в прямом эфире! Интервьюер Алексей Ушаровский (Oracle, Сбер) задаст реальные вопросы разработчику-добровольцу и разберёт его ответы. В конце — время вопросов ментору из зала. Что узнаешь на эфире: 📂 Какие вопросы задают на собеседованиях и зачем 📂 Как подготовиться, чтобы получить достойный оффер 📂 Чего ждут от кандидатов на Middle Java Запишись на эфир в боте ШОРТКАТ → @shortcut_sh_bot

Утренний рефакторинг с Дженной Ортегой* На относительно простом примере показываю как можно сделать программу «снова великой»
Утренний рефакторинг с Дженной Ортегой* На относительно простом примере показываю как можно сделать программу «снова великой». Ключевые стадии рефакторинга, Java, эмулятор и Jenna Ortega в нейросетевом исполнении. https://habr.com/ru/articles/886890/ 👉@BookJava

⚡️ Кастомный toString() в Java – как сделать правильно? Сегодня поговорим про метод toString() в Java. Казалось бы, мелочь, но грамотная реализация этого метода значительно упрощает отладку и логирование. ❌ Как делать НЕ стоит Обычная ошибка – использовать toString() по умолчанию или писать его вручную без четкой структуры:

public class User {
    private String name;
    private int age;

    // Ошибочный вариант
    @Override
    public String toString() {
        return "User[name=" + name + ", age=" + age + "]";
    }
}
Минусы такого подхода: - Код громоздкий и трудно читаемый - При добавлении новых полей легко забыть их добавить в toString() - Нет удобного форматирования ✅ Как делать правильно Лучший вариант – использовать String.format() или StringJoiner, но ещё лучше – библиотеку Lombok или Objects.toString():

import lombok.ToString;

@ToString
public class User {
    private String name;
    private int age;
}
Или без Lombok, но читабельно:

import java.util.Objects;

public class User {
    private String name;
    private int age;

    @Override
    public String toString() {
        return String.format("User{name='%s', age=%d}", name, age);
    }
}
Плюсы: - Автоматически форматируется - Читаемый и поддерживаемый код - Легко расширять Используйте toString() осознанно, и ваш код станет лучше! Какой способ используете вы? 👉@BookJava

Используем Lombok правильно: Разбираемся с @Slf4j Сегодня я расскажу вам о @Slf4j из библиотеки Lombok и о том, как его правильно использовать, чтобы ваш код стал чище и удобнее. Что такое @Slf4j? Это аннотация, которая добавляет в ваш класс статическое поле логгера org.slf4j.Logger. Вместо того чтобы писать:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyService {
    private static final Logger log = LoggerFactory.getLogger(MyService.class);
}
Достаточно одной аннотации:

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MyService {
}
Теперь в коде можно просто писать:

log.info("Приложение запущено");
log.error("Произошла ошибка: {}", exception.getMessage());
На что обратить внимание? 1️⃣ @Slf4j использует SLF4J API, поэтому вам все равно потребуется подключить реализацию логирования, например Logback:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>
2️⃣ Если нужен другой логгер, можно использовать альтернативные аннотации: - @Log — для java.util.logging - @Log4j — для Apache Log4j - @Log4j2 — для Log4j2 3️⃣ Не забывайте про уровень логирования! Используйте debug для отладки, info для полезных сообщений, warn для предупреждений и error для ошибок. Вывод: @Slf4j — это удобный инструмент, который избавляет от лишнего кода и упрощает работу с логированием. Если вы еще не используете Lombok для логирования, самое время попробовать! 👉@BookJava

🦾👩‍💻Хардкорный тест по языку Java👩‍💻🦾 👩‍💻 Пройдите тест из 21 вопроса и проверьте, насколько вы готовы к обучению на
🦾👩‍💻Хардкорный тест по языку Java👩‍💻🦾 👩‍💻 Пройдите тест из 21 вопроса и проверьте, насколько вы готовы к обучению на углубленном курсе «Разработчик на Spring Framework» от OTUS. Сможете сдать - пройдете на курс по спеццене! 💻 За 5 месяцев обучения вы освоите современные возможности Spring, научитесь быстро проходить путь от идеи до production-grade, создавать Web-приложения на микросервисной архитектуре и решать высокоуровневые задачи по разработке. ⏰ Время прохождения теста ограничено 30 минут 👉 ПРОЙТИ ТЕСТ: https://vk.cc/cJ4GlS Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

🚀 Используем Optional правильно в Java Сегодня разберем Optional – мощный инструмент, который помогает избежать NullPointerException. Но многие используют его неправильно! Давайте посмотрим, как его применять эффективно. ❌ Как делать НЕ надо:

Optional<String> optional = Optional.ofNullable(getValue());
if (optional.isPresent()) {
    System.out.println(optional.get());
}
Почему плохо? - get() без проверки – потенциальная ловушка. - Лишний if – можно сделать проще. ✅ Как надо:

Optional.ofNullable(getValue()).ifPresent(System.out::println);
или, если нужно значение по умолчанию:

String value = Optional.ofNullable(getValue()).orElse("Default Value");
Крутые приемы с Optional: ✔ orElseGet – лениво вычисляет значение ✔ orElseThrow – выбрасывает исключение, если Optional пуст ✔ map и flatMap – позволяют трансформировать данные 🔥 Советы: 1️⃣ Не используйте Optional для полей классов – это не сериализуемо. 2️⃣ Не передавайте Optional в аргументах методов – это антипаттерн. 3️⃣ Optional хорош для возвращаемых значений – используйте его вместо null. Как вы используете Optional в своих проектах? Делитесь в комментариях! 👉@BookJava

Дикая Java «Безопасный язык» говорили они, «четкая спецификация» говорили они, «Java не даст вам выстрелить себе в ногу» и пр
Дикая Java «Безопасный язык» говорили они, «четкая спецификация» говорили они, «Java не даст вам выстрелить себе в ногу» и прочее в таком духе. Реальность же оказалась куда веселее официальной документации и мнений экспертов. «JVM темна и полна ужасов». (ц) https://habr.com/ru/articles/886080/ 👉@BookJava

⚡️ Квиз на знание Java Пройти тестирование — сложно! А ты справишься? 22 вопроса, 30 минут Проверь себя - пройди квиз и оцени
⚡️ Квиз на знание Java Пройти тестирование — сложно! А ты справишься? 22 вопроса, 30 минут Проверь себя - пройди квиз и оцени свой уровень навыков, а также свою готовность к обучению на курсе — «Java Developer. Advanced» от Отус. 👩‍💻 На курсе ты научишься профилировать приложения, настраивать GC, работать с реактивными подходами и мониторить метрики в Grafana. Пройдешь весь путь от JVM до Kubernetes, научишься анализировать «горячие точки», оптимизировать приложения и настраивать интеграции с Prometheus. ➡️ ПРОЙТИ ТЕСТ: https://vk.cc/cIZDax Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

🧵 Разбираемся с CompletableFuture в Java Сегодня я хочу рассказать вам про CompletableFuture — мощный инструмент для работы
🧵 Разбираемся с CompletableFuture в Java Сегодня я хочу рассказать вам про CompletableFuture — мощный инструмент для работы с асинхронными операциями в Java. Если вам приходилось ждать выполнения долгих задач в коде и хотелось бы улучшить производительность, то этот пост для вас! 🚀 🔹 Что такое CompletableFuture? CompletableFuture — это часть java.util.concurrent с Java 8, которая позволяет выполнять асинхронные задачи и удобно комбинировать их. В отличие от обычного Future, CompletableFuture поддерживает цепочки вызовов, композицию задач и обработку ошибок. 🔹 Пример использования Допустим, у нас есть сервис, который загружает данные по сети. Обычный подход синхронного вызова будет блокировать поток, но с CompletableFuture мы можем избежать этого:

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            System.out.println("Загружаем данные...");
            sleep(2000);
            return "Данные загружены";
        }).thenApply(data -> {
            System.out.println("Обрабатываем: " + data);
            return data.toUpperCase();
        }).thenAccept(System.out::println)
          .exceptionally(ex -> {
              System.out.println("Ошибка: " + ex.getMessage());
              return null;
          });

        sleep(3000); // Даем время асинхронной операции завершиться
    }

    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
🔹 Разбор кода 1️⃣ supplyAsync() — запускает асинхронную задачу в отдельном потоке. 2️⃣ thenApply() — позволяет обработать результат (например, изменить его формат). 3️⃣ thenAccept() — принимает готовый результат и выполняет действие. 4️⃣ exceptionally() — обрабатывает возможные ошибки. 🔹 Зачем это нужно? ✅ Улучшает производительность за счет асинхронного выполнения. ✅ Избегает блокировки основного потока. ✅ Позволяет легко комбинировать операции. Используете ли вы CompletableFuture в своих проектах? Делитесь опытом в комментариях! 👇 👉@BookJava