Java for Beginner
747 subscribers
719 photos
202 videos
12 files
1.16K links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Реактивное программирование

Обработка ошибок в реактивных стримах

Представьте ошибки как пороги в потоке событий: без обработки они останавливают течение, но с правильными операторами — поток продолжается, минимизируя простои. Это решает проблемы из первого поста: вместо жёстких сбоев в потоках или Future, где ошибка рушит всё, реактивный подход даёт контроль и устойчивость.

Обработка ошибок в Reactor строится на жизненном цикле: когда исключение возникает в потоке (в map, flatMap или источнике), срабатывает onError, прерывая onNext и onComplete. Но вместо того чтобы "падать", вы можете трансформировать ошибку в данные, повторить попытку или логировать.
Операторы — декларативные: добавляете в цепочку, и Reactor управляет асинхронностью, backpressure и распространением ошибок. Это делает код resilient (устойчивым): приложение не крашится, а адаптируется.


Базовая реакция: doOnError и onErrorMap

Сначала — простые операторы для наблюдения и модификации ошибок, без изменения потока.

- doOnError: дополнительная реакция на ошибку, как "хук" (зацепка). Полезен для логирования или метрик, не влияет на основной onError.
- onErrorMap: преобразует исключение в другое, для кастомизации (например, оборачивает в бизнес-ошибку).


Пример на Flux:
import reactor.core.publisher.Flux;
import java.io.IOException;

Flux<String> riskyFlux = Flux.just("данные1", "данные2").map(data -> {
if (data.equals("данные2")) throw new IOException("Сбой ввода-вывода");
return data.toUpperCase();
});

riskyFlux
.doOnError(e -> System.err.println("Лог: " + e.getMessage())) // Логируем
.onErrorMap(e -> new RuntimeException("Обёрнутая ошибка: " + e)) // Преобразуем
.subscribe(
System.out::println,
error -> System.err.println("Финальная ошибка: " + error) // onError в подписке
);

// Вывод: "ДАННЫЕ1", потом лог "Сбой ввода-вывода", и финальная "Обёрнутая ошибка: ..."

Здесь doOnError срабатывает перед onErrorMap, а подписка ловит модифицированную ошибку. Это асинхронно: если ошибка в асинхронном подпотоке (flatMap), Reactor передаёт её downstream (дальше по цепи) без блокировок.


На Mono: аналогично, но для одиночного элемента.

Эти операторы решают проблему традиционных try-catch: вместо разбросанных блоков, всё в конвейере, читаемо и централизовано.


Восстановление: onErrorReturn и onErrorResume

Когда ошибка — не конец света, используйте fallback.

- onErrorReturn: возвращает фиксированное значение вместо ошибки. Простой запасной вариант.
- onErrorResume: более гибкий — заменяет ошибку новым Publisher (Mono/Flux). Можно генерировать динамически, в зависимости от исключения.


Пример с onErrorReturn:
Mono<String> httpMono = Mono.fromCallable(() -> {
// Симулируем HTTP-запрос
throw new RuntimeException("Сервер не отвечает");
}).onErrorReturn("Кэшированные данные");

httpMono.subscribe(System.out::println); // Вывод: "Кэшированные данные", потом onComplete

Здесь ошибка преобразуется в значение, поток завершается успешно.


С onErrorResume — условно:
Flux<Integer> calcFlux = Flux.range(1, 5).map(i -> {
if (i == 3) throw new ArithmeticException("Деление на ноль");
return 10 / (i - 3); // Симуляция
}).onErrorResume(e -> {
if (e instanceof ArithmeticException) {
return Flux.just(0, 0); // Fallback на нули
} else {
return Flux.error(e); // Пропустить другие ошибки
}
});

calcFlux.subscribe(System.out::println); // Вывод: элементы до ошибки, потом 0, 0, onComplete


onErrorResume позволяет ветвление: проверь тип ошибки и верни альтернативный поток. Это асинхронно: если fallback — Mono.delay, оно подождёт без блокировки.

Почему лучше CompletableFuture.handle?
Нет вложенных колбэков — цепочка линейна, ошибки интегрированы в конвейер.



#Java #middle #Reactor #doOnError #onErrorMap
👍2
Retry: повтор попыток при ошибке

Retry — для transient (временных) ошибок: сеть, временный сбой. Повторяет upstream (источник) заданное число раз.

- retry(long times): простая повторка.
- retryWhen(Retry strategy): с кастомной логикой (backoff — задержка, условия).


Пример базовый:

Mono<String> flakyMono = Mono.defer(() -> {
if (Math.random() > 0.3) throw new RuntimeException("Временный сбой");
return Mono.just("Успех");
}).retry(3); // Повторить 3 раза

flakyMono.subscribe(System.out::println, Throwable::printStackTrace);

Здесь retry повторяет весь Mono при ошибке, до успеха или исчерпания попыток. Если все попытки fail — финальный onError.


С retryWhen для экспоненциальной задержки (backoff):
import reactor.util.retry.Retry;

flakyMono.retryWhen(Retry.backoff(3, Duration.ofSeconds(1))); // 3 попытки с задержкой 1с, 2с, 4с


Это предотвращает "молоток" (hammering) сервера: ждёт перед retry. Асинхронно: задержки не блокируют поток.

Retry решает боли блокировок: вместо цикла с sleep в традиционном коде, декларативно и эффективно.



Практические советы и подводные камни

- Комбинируйте: riskyFlux.doOnError(log).onErrorResume(fallback).retry(2) — лог + retry + fallback.
- Условия: в onErrorResume используйте instanceof для типов ошибок, чтобы не catch всё подряд.
- Глобально: используйте Hooks.onErrorDropped для непойманных ошибок (редко).
- Камень: retry на бесконечных потоках — вечный цикл; добавьте timeout() или maxAttempts.
- Тестирование: StepVerifier.create(flux).expectErrorMatches(e -> e instanceof IOException).verify();

В практике: в WebFlux — контроллер возвращает Mono с retry для внешних API, onErrorReturn для кэша.
плавному восстановлению, экономя ресурсы и упрощая код.



#Java #middle #Reactor #doOnError #onErrorMap
👍2
Что выведет код?

import reactor.core.publisher.Mono;

public class MonoExample {
public static void main(String[] args) {
Mono.just("Start")
.doOnNext(System.out::print)
.then(Mono.fromRunnable(() -> System.out.print("Middle")))
.thenReturn("End")
.subscribe(System.out::print);
}
}


#Tasks
👍1
Варианты ответа:
Anonymous Quiz
19%
StartMiddle
13%
MiddleEnd
6%
StartEnd
63%
StartMiddleEnd
Вопрос с собеседований

Чем отличается LinkedHashMap от HashMap?🤓

Ответ:

LinkedHashMap
сохраняет порядок вставки элементов (или порядок доступа при включённом режиме accessOrder).

HashMap порядок не гарантирует.

LinkedHashMap удобен для кэшей, когда важен порядок добавления или использования.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🗓 История IT-технологий сегодня — 11 октября


ℹ️ Кто родился в этот день

Александр Андреевич Кузнецов (11 октября 1944 года — 6 января 2022 года, Москва, Россия) — советский и российский учёный-педагог, академик РАО (1999), вице-президент РАО. Более 30 лет проработал в Институте содержания и методов обучения РАО, где возглавлял лабораторию дидактики информатики, являлся академиком-секретарём Отделения общего среднего образования РАО, впоследствии был избран вице-президентом Российской академии образования.

🌐 Знаковые события

1961 — на Семипалатинском полигоне осуществлён первый подземный ядерный взрыв.

1999 — Британский астроном Джон Мюррей (John Murray), исходя из своих расчётов, заявил, что вокруг Солнца по десятой орбите движется огромная планета, по размерам больше Юпитера.


#Biography #Birth_Date #Events #11Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
С 04.10 по 10.10
Предыдущий пост(с 27.09 по 03.10)

Воскресный мотивационный пост:
А сколько вы жмете от груди?

Выбранная голосованием тема:
Аспектно-ориентированное программирование в Java (AOP)

Запись встреч/видео:
Не проводилось

Обучающие статьи:

Реактивное программирование
Базовые операторы в Reactor: map, filter, flatMap
Комбинации потоков в Reactor: concat, merge и другие
Обработка ошибок в реактивных стримах

Java:
Коллекции в Java
Глава 3. Set — множества
Интерфейс Set. Особенности множеств
Реализации: HashSet, LinkedHashSet, TreeSet

Полезные статьи и видео
:

Защита своего приложения с помощью JWT и Spring Security
Идемпотентность: больше, чем кажется


Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍3
Завтра жду всех на встречу.

Как всегда в 16:00 МСК.

Приходите ☺️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🗓 История IT-технологий сегодня — 12 октября


ℹ️ Кто родился в этот день

Илья Алексеевич Житомирский (12 октября, 1989, Москва, СССР — 12 ноября, 2011, Сан-Франциско, США) — российско-американский разработчик программного обеспечения, сооснователь социальной сети Diaspora.

Оле-Йохан Даль (норв. Ole-Johan Dahl, 12 октября 1931 года, Мандал — 29 июня 2002 года, Осло) — норвежский учёный в области теории вычислительных систем, лауреат премии Тьюринга. Вместе с Кристеном Нюгором является одним из разработчиков основ объектно-ориентированного программирования, а также первого объектно-ориентированного языка программирования Симула.

Брэм Коэн (12 октября 1975 г. Нью-Йорк) — американский программист, автор протокола BitTorrent, оказавшего большое влияние на распределённую передачу файлов и P2P-системы.


🌐 Знаковые события

1964 — с космодрома Байконур запущен трёхместный космический корабль «Восход-1». Впервые осуществлён полёт многоместного корабля, также впервые полёт осуществлялся без скафандров.

1994 — межпланетная станция НАСА «Магеллан», работавшая с 1989 года, сгорела в атмосфере Венеры


#Biography #Birth_Date #Events #12Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
This media is not supported in your browser
VIEW IN TELEGRAM
Чего ты тут забыл? 🧐

⚠️ AHTUNG ⚠️

Демотивационная статья. Читать с осторожностью.

Написано открыто, потому что все равно статьи никто не читает 😎


Мысли вслух, когда устаешь быть мотиватором.


И чего все лезут в IT?
И почему вдруг ты решил, что сможешь?
Если ты вдруг научился устанавливать Windows и твои близкие назвали тебя "Наш программист", это совсем не значит, что ты им стал.


Ты правда думаешь, что тебе тут рады?

Что в IT тебя ждут с открытыми объятиями, чашкой кофе и оффером на 300к?
Нет, дружище. Здесь и без тебя тесно.

Каждый день тысячи таких же "новоиспечённых айтишников" лезут в hh, как в последний вагон уходящего поезда.
Все с одинаковыми мечтами, одинаковыми курсами и одинаковыми "Hello, world" и TODO-шками написанными по гайдам 10-летней давности.

И все уверены, что именно они — будущие синьоры, тимлиды и архитекторы.


А вот нихерашеньки 🖕


Реальность №1: ты никому не нужен

Компаний, которым нужны джуны без опыта, но с горящими глазами — меньше, чем вакансий на дирижёра без слуха.
А если вдруг ты туда попал — готовься к тоннам легаси, таскам уровня "почини сервер", и наставнику, который ненавидит тебя и свою жизнь.


Реальность №2: Пока ты учил, всё, что ты выучил — уже устарело

Ты только понял, как работает Spring Boot?
Поздравляю. Он уже обновился, и теперь не работает так, как ты думаешь.
Java? Kotlin поджимает. Kotlin? Уже шепчут про Rust и Go.
А пока ты разбираешься с зависимостями — твой мозг тихо плачет и просит пива.


Не хочешь каждый день учиться? Закинут на антресоль как раритет или выкинут на свалку.

И надо оно тебе?

Реальность №3: денег не будет

Сразу точно не будет. А сможешь ли ты дотерпеть?
Все эти истории про "начал с нуля и через год 250к" — для курсов и буткемпов.

Веришь? Значит ты доверчивый ослик
🫏.

В текущей реальности ты, скорее всего, будешь рад, если найдешь стажировку на 20–30 тысяч без накрутки опыта.
А потом ещё три года будешь доказывать, что не зря ешь офисные печеньки.
😄

Реальность №4: ты не выдержишь, если пришёл “просто попробовать”

Если ты думаешь, что сегодня IT, все еще это лёгкий способ заработать — ты точно ошибся.

Говорят лет 5-7 назад брали только за то что ты умел идею запустить.


А сегодня если ты пришёл за “удалёнкой с видом на море” — тебя сожрёт реальность дедлайнов, ревью и Jira. Погребет под собой тонна знаний по кору, sql, спрингу, докеру, многопоточке, коллекциям, ci-cd, кафке, монго, куберу...
И ведь это только начало
🥵

Ты еще уверен что оно тебе надо?


Так зачем ты сюда пришёл?

Если хочешь лёгкой работы — уходи. Тебя тут никто не ждет.
Если хочешь “самореализации” — купи мольберт.
Хочешь денег - иди в чиновники и воруй.

Но если ты хочешь понимать, как работает цифровой мир, и готов к боли — оставайся.


Потому что программирование — это не про успех.

Это про любопытство, упрямство и мазохизм в одной IDE
☺️😉🤣


Ты такой?

Ты считаешь что сможешь?
И не боишься возможно поломать свой мозг, комп и возможно жизнь об программирование?

Тогда ты тот для кого я веду этот канал.

Остальные, залетные, кто пришел сюда за "откровениями", "посмотреть" и завтра выйдет - не стоят моего труда.

А вот тем кто готов бороться (как и я сам) я посвящаю каждую строчку, каждого поста.

Остальным — удачи. А нам — кофе и терпения.

Я с вами☺️😉

Ваш Oleborn
🎶


#мои_мысли
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥81
Не забыли про встречу?

В 16:00 Бот выдаст ссылку)

Приходите)
👍1
@JFB_admin_bot

пишите боту, он даст ссылку на встречу))

Общение лучше начать с команды /start

Залетайте)
👍1
gRPC и .proto.

Разбор и демонстрационный код

В сегодняшнем видео мы рассмотрели что такое gRPC.

- Написали и запустили простой демонстрационный код.
- Разобрали в чем отличие от REST, как это работает.
- Написали файл .proto, разобрали какие типы данных в нем применяются.
Как всегда немного подебажили
😜

Репозиторий на GitHub ждет Ваших звезд ☺️

Ссылка на Youtube
Ссылка на Рутьюб

Смотрите, ставьте лайки, подписывайтесь на каналы!✌️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🗓 История IT-технологий сегодня — 13 октября


ℹ️ Кто родился в этот день

Сильвио Микали (итал. Silvio Micali; род. 13 октября 1954) — итальянско-американский криптограф, лауреат премии Тьюринга; основоположник современных подходов в криптографии и теории безопасных протоколов.

Скотт Мэрфи (родился 13 октября 1954 года) — американский разработчик игр, программист, сценарист. Является разработчиком нескольких приключенческих игр, в основном для фирмы Sierra On-Line. Больше всего он известен как создатель серии Space Quest.


🌐 Знаковые события

1884 — Гринвич утверждён как место прохождения нулевого меридиана.


#Biography #Birth_Date #Events #13Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Коллекции в Java

Глава 3. Set — множества

Методы add, remove, contains

Методы add, remove и contains — это основные операции для добавления, удаления и проверки элементов в Set. Они наследуются от интерфейса Collection, но в Set имеют специфику из-за уникальности элементов.

add(E e): Добавляет элемент в множество, если его еще нет. Возвращает boolean: true, если добавлен (элемент был уникален), false — если уже существовал (дубликат игнорируется).
remove(Object o): Удаляет элемент, если он существует. Возвращает boolean: true, если удален (элемент был), false — если не найден.
contains(Object o): Проверяет, содержит ли множество элемент. Возвращает boolean: true, если есть, false — если нет.


Эти методы работают за O(1) в HashSet/LinkedHashSet (средний случай) и O(log n) в TreeSet.

Общие нюансы:
Все методы используют equals() для сравнения элементов (и hashCode() в Hash-based реализациях).
Null: Разрешен в HashSet/LinkedHashSet (один), но в TreeSet вызывает NullPointerException при сравнении.
Изменение множества: Методы модифицируют Set in-place (на месте).
Thread-safety: Не гарантирована — используйте synchronized версии для многопоточности.
Generics: Set add(Integer) — ошибка компиляции (типобезопасность).



Метод add(E e): Добавление элементов

add() — основной способ наполнения Set. Если элемент уже есть (по equals()), он не добавляется, и возвращается false.

Поведение в реализациях:
HashSet: Добавляет в хэш-таблицу. Если хэш-коллизия, проверяет equals() в цепочке.
LinkedHashSet: Аналогично HashSet, но обновляет ссылки в списке для порядка вставки (только если добавлен).
TreeSet: Добавляет в дерево, сравнивая через compareTo() или Comparator. Если равен 0 — не добавляет.


Возвращаемое значение: true — добавлен (новый), false — уже был.

Исключения: NullPointerException в TreeSet для null; ClassCastException в TreeSet, если элемент не Comparable.

Нюансы:
Если Set полный (редко, так как resizable), может быть OutOfMemoryError.
Для custom объектов: Без правильного equals()/hashCode() может добавить "дубликаты" (по значению, но не по ссылке).
Модификация объекта после добавления: Не изменяйте поля, влияющие на equals/hashCode (например, в HashSet объект может "потеряться").


Пример кода для add():
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet;
import java.util.Set;

public class Main {
public static void main(String[] args) {
// HashSet
Set<String> hashSet = new HashSet<>();
boolean added1 = hashSet.add("Яблоко"); // true
boolean added2 = hashSet.add("Яблоко"); // false (дубликат)
System.out.println(hashSet); // [Яблоко]

// LinkedHashSet
Set<String> linkedSet = new LinkedHashSet<>();
linkedSet.add("Яблоко");
linkedSet.add("Банан");
linkedSet.add("Яблоко"); // false
System.out.println(linkedSet); // [Яблоко, Банан] — порядок вставки

// TreeSet
Set<Integer> treeSet = new TreeSet<>();
treeSet.add(5);
treeSet.add(1);
treeSet.add(5); // false
System.out.println(treeSet); // [1, 5] — отсортировано
}
}

Вывод показывает уникальность и особенности каждой реализации.



#Java #для_новичков #beginner #Collections #Set #add #remove #contains
Метод remove(Object o): Удаление элементов

remove() удаляет элемент, если он найден по equals(), и возвращает true/false.

Поведение в реализациях:
HashSet: Находит по хэшу, затем equals() — O(1).
LinkedHashSet: Аналогично, плюс обновляет ссылки списка.
TreeSet: Ищет по compareTo() — O(log n), удаляет узел дерева.


Возвращаемое значение: true — удален, false — не найден.

Исключения: NullPointerException в TreeSet для null; ClassCastException, если тип не совместим.


Нюансы:

Аргумент Object: Можно удалять по объекту любого типа, но сравнивает equals().
После remove: Размер уменьшается, итераторы обновляются.
Для custom: Зависит от equals().

Пример кода для remove():
import java.util.HashSet;
import java.util.Set;

public class Main {
public static void main(String[] args) {
Set<String> fruits = new HashSet<>();
fruits.add("Яблоко");
fruits.add("Банан");

boolean removed1 = fruits.remove("Яблоко"); // true
boolean removed2 = fruits.remove("Апельсин"); // false (не найден)

System.out.println(fruits); // [Банан]
}
}

Аналогично для других реализаций: В TreeSet remove сохраняет сортировку.



Метод contains(Object o): Проверка наличия

contains() проверяет, есть ли элемент в Set по equals().

Поведение в реализациях:
HashSet: O(1) — хэш + equals().
LinkedHashSet: O(1), но с overhead списка.
TreeSet: O(log n) — поиск в дереве.


Возвращаемое значение: true — есть, false — нет.

Исключения: Аналогично remove: NPE в TreeSet для null.


Нюансы:
Быстрее, чем в List (O(n)), идеально для проверок уникальности.
Для больших Set: HashSet fastest.


Пример кода для contains():
import java.util.HashSet;
import java.util.Set;

public class Main {
public static void main(String[] args) {
Set<String> fruits = new HashSet<>();
fruits.add("Яблоко");

System.out.println(fruits.contains("Яблоко")); // true
System.out.println(fruits.contains("Банан")); // false
}
}



Полезные советы для новичков

add для уникальности: Используйте возвращаемое значение для логики (if (!set.add(e)) { "Дубликат!"; }).
remove/contains для null: Тестируйте — в HashSet работает, в TreeSet — нет.
Custom объекты: Переопределяйте equals/hashCode (IDE: Generate → equals() and hashCode()).
Эффективность: Для частых contains — HashSet; для сортировки — TreeSet.
Комбинируйте: Set для фильтра, затем List для порядка.
Ошибки: ClassCastException в TreeSet без Comparable; ConcurrentModification при модификации в цикле (используйте Iterator).



#Java #для_новичков #beginner #Collections #Set #add #remove #contains
👍1