Библиотека Java разработчика
10.8K subscribers
1.14K photos
564 videos
58 files
1.44K links
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate.


По всем вопросам @evgenycarter

РКН clck.ru/3KoGeP
Download Telegram
👩‍💻 Resilience4j. RateLimiter

Приглашаем на открытый урок.

🗓 24 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса«Java Developer. Professional».

Где мы разберем:

✔️Что такое RateLimiter?
✔️Настройка и особенности.

Урок будет полезен тем, кто хочет:
✔️Защитить приложения от пиковых нагрузок и обеспечить высокую доступность.
✔️Использовать ключевые инструменты Resilience4j для управления трафиком.
✔️Глубже понять, как писать надёжные микросервисы и оптимизировать их под реальные сценарии.

В результате урока вы:
✔️Разберётесь, как работает RateLimiter и в чём его польза при ограничении запросов.
✔️Получите несколько примеров настройки и сможете применять эти приёмы в базовых сценариях.

Спикер Сергей Петрелевич — опытный Java/Kotlin-разработчик и преподаватель.

🔗 Ссылка на регистрацию: https://vk.cc/cIJZkN

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🔥 Исключения в Java: что не так с catch (Exception e)?

Давайте разберем одну из самых частых ошибок, которую я вижу в коде даже опытных Java-программистов. Это перехват всех исключений сразу:


try {
// код, который может выбросить исключение
} catch (Exception e) {
e.printStackTrace();
}


📌 В чем проблема?
1️⃣ Глушение ошибок – если просто печатать stacktrace, но не обрабатывать ошибку корректно, это может привести к неожиданным последствиям. Например, приложение продолжит работу в некорректном состоянии.
2️⃣ Ловим слишком много – перехватывая Exception, мы ловим все исключения, включая RuntimeException, что делает отладку сложнее.
3️⃣ Скрытые ошибки – если в коде, например, ошибка валидации и мы просто пишем e.printStackTrace(), пользователь так и не узнает, что пошло не так.

💡 Как делать правильно?
Лучше перехватывать конкретные исключения и обрабатывать их осмысленно:


try {
// код
} catch (IOException e) {
log.error("Ошибка ввода-вывода", e);
} catch (NumberFormatException e) {
log.warn("Некорректный формат числа", e);
} catch (Exception e) {
log.error("Непредвиденная ошибка", e);
throw e; // Не глушим ошибку, пробрасываем дальше
}


Вывод: Используйте catch (Exception e) только если действительно уверены, что вам нужно обработать все возможные ошибки. В остальных случаях — ловите конкретные исключения и работайте с ними правильно! 🚀

Как вы относитесь к catch (Exception e)? Часто ли видите его в коде? Давайте обсудим в комментариях! 💬

👉@BookJava
👍6👎1
⚔️Ваши микросервисы не дружат между собой?

Сначала один сервис завис, потом второй, а в логах — хаос. Конфиги разбросаны по разным файлам, API ломаются после каждого релиза, а тестировщики смотрят на вас как на главного злодея проекта.

👩‍💻 Есть способ навести порядок. Spring Cloud помогает микросервисам работать как единая система: управлять конфигурациями, находить друг друга без лишних костылей и не падать при каждом обновлении.

🦾Разберём, как это сделать, на открытом уроке «Экосистема Spring Cloud».

Когда: 25 февраля в 20:00 (мск).

Вы узнаете, как использовать Service Discovery, API Gateway и Config Server. А еще получите скидку на большое обучение «Java Developer. Advanced».

Не ждите, пока сервисы начнут воевать друг с другом.

🔗 Регистрируйтесь прямо сейчас: https://vk.cc/cIL61o

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👏1
Media is too big
VIEW IN TELEGRAM
Spring Data JDBC. Проблемы известные, проблемы неизвестные
Михаил Поливаха

Spring Data JDBC — относительно новый модуль Spring Data. У него своя концепция, свои фичи, свои баги и проблемы. Часть этих проблем известна аудитории и описана в документации. Однако иногда документация врет или недоговаривает. К тому же есть некоторые неочевидные детали реализации, которые могут смутить пользователей библиотеки. Это касается многих аспектов — от генерации SQL до маппинга сущностей.

Во время доклада мы посмотрели на ряд подобных сюрпризов, обсудим, баг это или фича и что разработчики планируют с этим делать. Также рассмотрели текущее состояние проекта Spring Data JDBC — над чем идет работа, что исправляется, а что пока нет.

источник

👉@BookJava
👍7
Please open Telegram to view this post
VIEW IN TELEGRAM
🤡10🥰1💩1
⚡️ 5 Фишек Lombok, Которые Вы Должны Знать!

Если вы до сих пор пишете геттеры и сеттеры вручную, самое время это прекратить! 😄

Вот 5 крутых аннотаций, которые обязательно нужно знать:

🔹 @Data – Комбо-аннотация, которая сразу добавляет @Getter, @Setter, @ToString, @EqualsAndHashCode и @RequiredArgsConstructor. Если у вас обычный POJO-класс, просто ставите @Data, и всё!

@Data
public class User {
private String name;
private int age;
}

📌 Результат: автоматическая генерация геттеров, сеттеров и других методов.

🔹 @Builder – Шаблон проектирования "Строитель" на стероидах!

@Builder
public class User {
private String name;
private int age;
}

📌 Теперь можно создавать объекты так:

User user = User.builder().name("Иван").age(25).build();


🔹 @Value – Неперезаписываемые (иммутабельные) объекты. Это как @Data, но с final полями и без сеттеров.

@Value
public class User {
String name;
int age;
}

📌 Отлично подходит для DTO!

🔹 @Slf4j – Логирование без бойлерплейта.

@Slf4j
public class App {
public static void main(String[] args) {
log.info("Привет, мир!");
}
}

📌 Не нужно вручную объявлять Logger — Lombok всё сделает за вас.

🔹 @SneakyThrows – Скрывает checked исключения (но осторожно! 😬).

@SneakyThrows
public void readFile(String path) {
Files.readAllLines(Path.of(path));
}

📌 Работает так, как будто исключений нет, но лучше использовать осознанно!

👉 Используете Lombok в проектах? Какая аннотация вам больше всего нравится? Делитесь в комментариях! 💬

👉@BookJava
👍14
🚀 Разбираемся с Optional в Java: избегаем NullPointerException!

Привет, друзья! Сегодня хочу поговорить о Optional, который помогает нам избежать NullPointerException и делает код чище.

Что такое Optional?
Optional<T> — это контейнер, который может содержать значение типа T или быть пустым. Это альтернатива null, которая явно указывает, что значение может отсутствовать.

🔥 Как использовать?
1️⃣ Создание Optional:

Optional<String> optional = Optional.of("Hello, Java!");

⚠️ Если передать null, будет NullPointerException.

2️⃣ Создание пустого Optional:

Optional<String> emptyOptional = Optional.empty();


3️⃣ Обёртка для возможного null:

Optional<String> nullableOptional = Optional.ofNullable(null);

Если передать null, Optional не упадёт, а просто будет пустым.

4️⃣ Проверка наличия значения:

optional.isPresent(); // true
optional.isEmpty(); // false

Но лучше использовать ifPresent:

optional.ifPresent(value -> System.out.println(value));


5️⃣ Получение значения с orElse:

String result = optional.orElse("Значение по умолчанию");


6️⃣ Получение с orElseGet:

String result = optional.orElseGet(() -> "Вычисленное значение");


7️⃣ Исключение, если значения нет:

String result = optional.orElseThrow(() -> new RuntimeException("Значение отсутствует!"));


8️⃣ Фильтрация:

Optional<String> filtered = optional.filter(val -> val.startsWith("Hello"));


9️⃣ Трансформация с map:

Optional<Integer> length = optional.map(String::length);


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

А как вы используете Optional? Делитесь в комментариях! 👇👇👇

👉@BookJava
👍11
👩‍💻 Создание 2D RPG игры на Java 👩‍💻

На открытом вебинаре вы создадите свою первую 2D RPG на Java с LibGDX, увидите, как код управляет миром игры, и освоите ключевые принципы программирования.

🗓 26 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java-разработчик».

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

Спикер Александр Фисунов — Senior Kotlin Developer в SSP Software на проекте ВТБ, опытный Java-разработчик и кандидат технических наук.

🔗 Ссылка на регистрацию: https://vk.cc/cINskz

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
👏2👍1🎉1
В чем разница между Iterator и ListIterator?

— Iterator может итерироваться только вперед, а ListIterator может и вперед и назад.

— ListIterator имеет дополнительные методы previous(), hasPrevious(), add(), set().

— ListIterator позволяет получить индекс текущего элемента.

— ListIterator может начать итерацию с произвольного индекса списка, а Iterator только с начала.

— ListIterator можно получить только из объектов, реализующих List, а Iterator из любой коллекции.

— ListIterator является более функциональным и позволяет вносить изменения в список во время итерации, Iterator — только читать.

— Итераторы безопасны для использования в многопоточных приложениях, а ListIterator — нет.

👉@BookJava
👍7🥰4
📌 Java: Как работает volatile и когда его использовать?


🔥 Что делает volatile?
Ключевое слово volatile гарантирует, что переменная всегда будет читаться из памяти, а не из кэша потока. Это помогает избежать проблем, когда один поток изменяет переменную, но другой поток продолжает работать со старым значением из кэша.

🔄 Разбираем на примере:

class SharedResource {
volatile boolean flag = false;

void changeFlag() {
flag = true;
}
}

class Worker extends Thread {
SharedResource resource;

Worker(SharedResource resource) {
this.resource = resource;
}

public void run() {
while (!resource.flag) {
// Ждём, пока флаг изменится
}
System.out.println("Флаг изменился! Поток завершает работу.");
}
}

public class VolatileExample {
public static void main(String[] args) throws InterruptedException {
SharedResource resource = new SharedResource();
Worker worker = new Worker(resource);

worker.start();
Thread.sleep(1000);

resource.changeFlag(); // Флаг изменится, и поток завершит цикл

worker.join();
}
}

🛑 Важные моменты:
volatile не делает операции атомарными. Если вам нужна атомарность, используйте synchronized или Atomic классы.
Он не предотвращает гонки данных, но гарантирует видимость изменений между потоками.
Лучше всего подходит для флагов завершения потоков и подобных сценариев.

👉@BookJava
👍6
⁉️👩‍💻Разрабатываете на Java, но проект на Spring превращается в черный ящик? Бины ведут себя непредсказуемо, конфигурация разрастается, а ошибка в одном модуле рушит всю систему.

Интервью на позицию Middle неудачно — не хватает уверенности в Spring.

🤝 Тем временем рынок требует специалистов, которые не просто знают Spring, а умеют строить продакшен-приложения с его помощью. Компании ищут разработчиков, которые понимают, как работают Spring Boot, Spring Security, Spring MVC и могут строить микросервисную архитектуру.

⚡️ На курсе «Разработчик на Spring Framework» мы закроем пробелы и дадим актуальные навыки. Практика на реальных кейсах, ревью заданий, тестовое собеседование — вы освоите Spring так, чтобы уверенно применять его в работе.

➡️ Пройдите вступительное тестирование и получите скидку на обучение: https://vk.cc/cIPLUU

🎫 Курс можно приобрести в рассрочку

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🔥 Разбираем CompletableFuture в Java: Асинхронность без боли

Всем добрый вечер! Сегодня расскажу про CompletableFuture — мощный инструмент для работы с асинхронными операциями в Java. Если вы хотите избавиться от блокирующего кода и сложных коллбэков, этот пост для вас!

🤔 Что такое CompletableFuture?
Это часть java.util.concurrent, позволяющая писать асинхронный код в декларативном стиле, без создания сложных цепочек Thread и ExecutorService.

🚀 Базовый пример использования
Допустим, у нас есть задача загрузить данные с сервера. Как это сделать асинхронно?


import java.util.concurrent.CompletableFuture;

public class AsyncExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
// Имитация долгого запроса
sleep(2000);
return "Данные загружены";
}).thenAccept(result ->
System.out.println("Результат: " + result)
);

System.out.println("Задача запущена, ждем результат...");
sleep(3000); // Чтобы main не завершился раньше времени
}

private static void sleep(int millis) {
try { Thread.sleep(millis); }
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
}

🔍 Разбираем код
1️⃣ supplyAsync() — выполняет операцию в фоновом потоке.
2️⃣ thenAccept()получает результат и выполняет код после завершения.
3️⃣ Главный поток продолжает работать, не блокируя выполнение.

🛠 Расширяем функционал
Можно комбинировать задачи:


CompletableFuture.supplyAsync(() -> "Привет, ")
.thenApply(greeting -> greeting + "мир!")
.thenAccept(System.out::println);

thenApply() изменяет данные перед следующим шагом.
thenAccept() выполняет финальную операцию.

📌 Где использовать?
🔹 Запросы к API без блокировки
🔹 Асинхронная обработка данных
🔹 Параллельные вычисления

👉 Вы уже использовали CompletableFuture? Делитесь опытом в комментариях! 💬

👉@BookJava
👍6🥰2
Подборка Telegram каналов для программистов

https://t.me/lifeproger Жизнь программиста. Авторский канал.
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/rabota1C_rus 1С Работа

Системное администрирование 📌
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин

https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux

1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С

Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах

Программирование Python 📌
https://t.me/pythonofff Python академия. Учи Python быстро и легко🐍
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python Rus

Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах

GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub

Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных

Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin

Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано

Разработка игр 📌
https://t.me/game_devv Все о разработке игр

Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов
https://t.me/books_reserv Книги для программистов

БигДата, машинное обучение 📌
https://t.me/bigdata_1 Data Science, Big Data, Machine Learning, Deep Learning

Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/coddy_academy Полезные советы по программированию
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста

QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика

Шутки программистов 📌
https://t.me/itumor Шутки программистов

Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_1 Статьи из "Хакера"

Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров

Английский 📌
https://t.me/UchuEnglish Английский с нуля

Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике

Excel лайфхак📌
https://t.me/Excel_lifehack

https://t.me/tikon_1 Новости высоких технологий, науки и техники💡
https://t.me/mir_teh Мир технологий (Technology World)

Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
👍3
Stream API: Обзор и Основные Методы

Stream API – мощный инструмент для обработки данных. Его основные принципы:
Композиция – построение логики из небольших, независимых и чистых функций.
Single Responsibility – каждый шаг выполняет одну конкретную операцию.

Такой подход обеспечивает:
✔️ Читаемость кода.
✔️ Отсутствие локальных переменных.
✔️ Линейную последовательность действий.

Основные компоненты Stream API
Любой поток состоит из трех ключевых частей:
1️⃣ Источник данных (коллекция, массив, файл и т. д.).
2️⃣ Промежуточные преобразования (filter, map и другие).
3️⃣ Конечная операция (коллекционирование, агрегация, перебор).

Способы создания стрима
Stream можно создать несколькими способами:

🔹 Из коллекции: collection.stream()
🔹 Из массива: Arrays.stream(array)
🔹 Из набора элементов: Stream.of(1, 2, 3)
🔹 Бесконечный поток: Stream.iterate(0, n -> n + 1)
🔹 Бесконечный поток с ограничением (Java 9): Stream.iterate(1, n -> n < 100, n -> n * 2)
🔹 Генерация элементов: Stream.generate(Math::random)
🔹 Диапазон значений:
- IntStream.range(1, 5) (1, 2, 3, 4)
- IntStream.rangeClosed(1, 5) (1, 2, 3, 4, 5)
🔹 Из файла: Files.lines(Path.of("file.txt"))
🔹 Из строки: "abc".chars()

Промежуточные операции
Stream API поддерживает множество преобразований. Наиболее распространенные:

✔️ Фильтрация: filter(Predicate<T>) – оставляет только элементы, соответствующие условию.
✔️ Удаление дубликатов: distinct() – исключает повторяющиеся элементы.
✔️ Ограничение количества: limit(n) – берет первые n элементов.
✔️ Сортировка: sorted() – упорядочивает элементы.

Менее очевидные операции
🔹 map(Function<T, R>) – применяет функцию к каждому элементу.
🔹 flatMap(Function<T, Stream<R>>) – «разворачивает» элементы из вложенных структур.
🔹 takeWhile(Predicate<T>) (Java 9) – берет элементы, пока выполняется условие.
🔹 dropWhile(Predicate<T>) (Java 9) – пропускает элементы, пока условие выполняется.
🔹 peek(Consumer<T>) – выполняет действие без изменения элементов (удобно для логирования).

Конечные операции
Стрим начинает обработку данных только при вызове конечной операции:

📌 Коллекционирование:
- collect(Collectors.toList()) – собирает в List.
- collect(Collectors.toSet()) – собирает в Set.

📌 Поиск элементов:
- findFirst() – первый элемент.
- findAny() – любой элемент (оптимизирован для параллельных потоков).
- anyMatch(Predicate<T>) – хотя бы один элемент удовлетворяет условию.
- allMatch(Predicate<T>) – все элементы удовлетворяют условию.
- noneMatch(Predicate<T>) – ни один элемент не удовлетворяет условию.

📌 Агрегация:
- min(Comparator<T>) – минимальный элемент.
- max(Comparator<T>) – максимальный элемент.
- count() – количество элементов.
- reduce(BinaryOperator<T>) – свертка элементов в одно значение.

📌 Побочные эффекты:
- forEach(Consumer<T>) – выполняет действие над каждым элементом.
- forEachOrdered(Consumer<T>) – выполняет действие, сохраняя порядок (важно для параллельных потоков).

Особенности работы со Stream API
1️⃣ Стрим – это не структура данных
Он лишь обходит источник, выполняя операции лениво.

2️⃣ Стрим нельзя использовать повторно
После вызова конечной операции повторное использование потока приведет к IllegalStateException.

3️⃣ Исходные данные не изменяются
Методы Stream API не модифицируют исходную коллекцию.

Разбор сложных случаев
Ошибочный код:

Stream.of(-1, 0, 1).max(Math::max).get();

Почему ошибка?
Метод max() принимает Comparator<T>, но Math.max(a, b) – это BiFunction<Integer, Integer, Integer>. Они не эквивалентны!

ℹ️ Решение:

Stream.of(-1, 0, 1).max(Integer::compareTo).get(); // Вернет 1


👉@BookJava
👍103🎉3🔥1🤨1
📝 Советы по оптимизации Java кода: избавляемся от лишнего

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

🚀 1. Избегайте ненужного создания объектов
Частая ошибка — создавать объекты там, где можно использовать уже существующие.

Плохо:

String str = new String("Hello"); // Избыточно

Хорошо:

String str = "Hello"; // Используем строковый пул

То же самое касается Integer.valueOf() вместо new Integer().

🔄 2. Используйте StringBuilder вместо конкатенации в цикле
Если вы объединяете строки в цикле, StringBuilder будет значительно быстрее.

Плохо:

String result = "";
for (int i = 0; i < 100; i++) {
result += i; // Создает новый объект String на каждой итерации
}

Хорошо:

StringBuilder result = new StringBuilder();
for (int i = 0; i < 100; i++) {
result.append(i);
}

Такой код работает в разы быстрее!

🏎 3. Правильно выбирайте коллекции
Используйте ArrayList, если не нужна частая вставка/удаление элементов в середине списка.
Используйте HashSet, если важны уникальные значения и не нужен порядок.
Используйте LinkedList, если нужна частая вставка/удаление в середине списка.

4. Не злоупотребляйте Stream API
Да, Stream API удобен, но иногда он замедляет код. Например:

Плохо:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, Integer::sum);

Хорошо:

int sum = 0;
for (int num : numbers) {
sum += num;
}

Цикл быстрее, потому что не тратит время на создание объектов и лямбды.

🔥 Вывод
Оптимизация — это не просто ускорение кода, но и улучшение его читаемости и поддержки. Используйте правильные структуры данных, избегайте лишних аллокаций, выбирайте оптимальные конструкции.

А какие советы по оптимизации Java кода используете вы? Пишите в комментариях! 👇 🚀

👉@BookJava
👍14
Бесплатный вебинар, который поможет начать изучение Spark с нуля!

👨‍💻🛠👨🏻‍💻 Кому будет полезно?
- Data-инженерам и аналитикам, работающим с большими объемами данных
- Программистам, переходящим с других технологий обработки данных на Spark

Не пропустите прямой эфир, где мы начнем изучение Big Data фреймворка и подробно разберем обработку графов с помощью Spark:
- ключевые понятия, включая структуру графов, а также алгоритмы, доступные в библиотеках GraphX и GraphFrames
- создание и обработку графов на основе различных типов данных
- эффективную работу с большими графами
- 2 популярных алгоритма для анализа данных: PageRank и Connected Components
- интеграцию графов в проекты
- практические примеры построения графов и их анализ

Все участники вебинара смогут продолжить обучение на курсе «Spark Developer» с выгодной скидкой.

➡️ Регистрация: https://vk.cc/cIVWCl

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
👍1
📝 Разбираем @Transactional в Spring: Где Подводные Камни?

Давайте обсудимм одну из самых популярных аннотаций в Spring — @Transactional. Многие знают, что она используется для управления транзакциями, но не все понимают, как она работает под капотом и какие проблемы могут возникнуть. Давайте разбираться!

🔍 Как работает @Transactional?
Когда вы помечаете метод @Transactional, Spring проксирует этот метод и оборачивает его в транзакцию. Это значит, что до начала метода открывается транзакция, а после — либо коммитится (если нет ошибок), либо откатывается (если есть исключение).

Но тут важно помнить:
🔹 @Transactional работает только на public методах (если используется Spring AOP).
🔹 Вызовы методов внутри одного класса не учитывают @Transactional. Если вызвать метод, аннотированный @Transactional, внутри другого метода того же класса, транзакция не создастся.
🔹 По умолчанию, транзакция откатывается только при RuntimeException. Если бросить checked-исключение, Spring не откатит транзакцию.

⚠️ Распространённые ошибки
Аннотация на private методе
Транзакция просто не будет работать, так как Spring AOP не перехватит вызов.

Вызов @Transactional метода внутри того же класса
Транзакция не создастся, так как вызов происходит без участия Spring Proxy. Решение — выносить такие методы в отдельный бин или использовать TransactionTemplate.

Неправильный rollback
Если в методе выбрасывается checked-исключение, Spring по умолчанию **не откатывает** транзакцию. Чтобы изменить это поведение, нужно явно указать `@Transactional(rollbackFor = Exception.class).

Как избежать проблем?
✔️ Всегда ставьте @Transactional на публичные методы.
✔️ Вызывайте @Transactional-методы только через Spring-управляемые бины.
✔️ Контролируйте rollback через rollbackFor.
✔️ Используйте propagation = REQUIRES_NEW, если хотите создать новую независимую транзакцию.

Кто сталкивался с неожиданным поведением @Transactional? Давайте обсудим в комментариях!

👉 @BookJava
👍13
🚀 AutoCloseable HttpClient в Java 21 🚀

HttpClient был обновлён и теперь реализует интерфейс AutoCloseable в Java 21. 🔥

👉 @BookJava
👍7
⚡️👩‍💻 Освой Java с нуля и начни карьеру успешного разработчика!

Мечтаешь вкатиться в IT, но думаешь, что уже поздно? Java — язык, на котором работают крупнейшие компании мира! Тебе точно найдется место.

🦾 Наше обучение на курсе "Java-разработчик" — это 3 ступени, которые проведут тебя от новичка до уверенного Middle-разработчика. Ты освоишь Spring, Hibernate, PostgreSQL, Docker, Kafka, Kubernetes и другие актуальные технологии!

Программа составлена практикующими экспертами, а диплом OTUS востребован в ведущих IT-компаниях. Наш партнер — СберКорус, разработчик передовых цифровых решений!

👉 Оставь заявку и получи скидку на курс: https://vk.cc/cIVZFZ

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
Абстракция в Java – что это и зачем нужна?

Одна из ключевых концепций ООП – абстракция. Мы постоянно используем её в Java, даже не задумываясь. Но давайте разберёмся, зачем она нужна и как правильно применять.

📌 Что такое абстракция?
Абстракция – это процесс выделения существенных характеристик объекта, скрывая при этом детали реализации. Это позволяет нам работать с объектами через их интерфейсы, а не конкретные реализации.

Пример из жизни:
Когда вы едете на машине, вам не нужно знать, как работает двигатель. Достаточно уметь жать на газ, тормозить и поворачивать руль. Вот это и есть абстракция – вам доступен только необходимый интерфейс, а детали скрыты.

🔹 Как реализуется абстракция в Java?
В Java абстракция достигается двумя способами:
1. Абстрактные классы (abstract class)
2. Интерфейсы (interface)

🚀 Абстрактные классы
Абстрактный класс может содержать как реализованные, так и абстрактные (без реализации) методы. Его нельзя создать через new, он служит основой для дочерних классов.


abstract class Vehicle {
abstract void start(); // абстрактный метод, без реализации

void stop() {
System.out.println("Машина остановилась");
}
}

class Car extends Vehicle {
@Override
void start() {
System.out.println("Запуск двигателя...");
}
}

public class Main {
public static void main(String[] args) {
Vehicle car = new Car();
car.start();
car.stop();
}
}

💡 Тут start() – это абстрактный метод, его реализация будет в Car. А вот stop() реализован в базовом классе.

🚀 Интерфейсы
Интерфейсы содержат только сигнатуры методов (до Java 8), а с Java 8 можно добавлять default и static методы.


interface Engine {
void start();
}

class ElectricCar implements Engine {
@Override
public void start() {
System.out.println("Электродвигатель включен!");
}
}

📌 Разница между интерфейсом и абстрактным классом в том, что интерфейсы описывают, что класс ДОЛЖЕН делать, а абстрактные классы – как он МОЖЕТ это делать.

🎯 Где применять абстракцию?
- Если у вас иерархия классов с общими методами – используйте абстрактный класс.
- Если вам нужно гибкое поведение без наследования – используйте интерфейсы.

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

Как вы чаще применяете абстракцию: через абстрактные классы или интерфейсы? Делитесь опытом в комментариях! 👇

👉@BookJava
👍5🤨1