Вот вы устроились IT-шником. Что нужно делать чтобы вас не сократили? 😉
Anonymous Poll
29%
Хорошо работать
42%
Иметь высокие экспертизы и стать незаменимым
3%
Пообещать засудить компанию
16%
Лизать зад тимлиду
11%
Подкармливать всех, в том числе и руководство, в офисе пончиками
👍1 1
Реактивное программирование
Обработка ошибок в реактивных стримах
Представьте ошибки как пороги в потоке событий: без обработки они останавливают течение, но с правильными операторами — поток продолжается, минимизируя простои. Это решает проблемы из первого поста: вместо жёстких сбоев в потоках или Future, где ошибка рушит всё, реактивный подход даёт контроль и устойчивость.
Обработка ошибок в Reactor строится на жизненном цикле: когда исключение возникает в потоке (в map, flatMap или источнике), срабатывает onError, прерывая onNext и onComplete. Но вместо того чтобы "падать", вы можете трансформировать ошибку в данные, повторить попытку или логировать.
Операторы — декларативные: добавляете в цепочку, и Reactor управляет асинхронностью, backpressure и распространением ошибок. Это делает код resilient (устойчивым): приложение не крашится, а адаптируется.
Базовая реакция: doOnError и onErrorMap
Сначала — простые операторы для наблюдения и модификации ошибок, без изменения потока.
- doOnError: дополнительная реакция на ошибку, как "хук" (зацепка). Полезен для логирования или метрик, не влияет на основной onError.
- onErrorMap: преобразует исключение в другое, для кастомизации (например, оборачивает в бизнес-ошибку).
Пример на Flux:
На Mono: аналогично, но для одиночного элемента.
Эти операторы решают проблему традиционных try-catch: вместо разбросанных блоков, всё в конвейере, читаемо и централизовано.
Восстановление: onErrorReturn и onErrorResume
Когда ошибка — не конец света, используйте fallback.
- onErrorReturn: возвращает фиксированное значение вместо ошибки. Простой запасной вариант.
- onErrorResume: более гибкий — заменяет ошибку новым Publisher (Mono/Flux). Можно генерировать динамически, в зависимости от исключения.
Пример с onErrorReturn:
С onErrorResume — условно:
onErrorResume позволяет ветвление: проверь тип ошибки и верни альтернативный поток. Это асинхронно: если fallback — Mono.delay, оно подождёт без блокировки.
Почему лучше CompletableFuture.handle?
Нет вложенных колбэков — цепочка линейна, ошибки интегрированы в конвейер.
#Java #middle #Reactor #doOnError #onErrorMap
Обработка ошибок в реактивных стримах
Представьте ошибки как пороги в потоке событий: без обработки они останавливают течение, но с правильными операторами — поток продолжается, минимизируя простои. Это решает проблемы из первого поста: вместо жёстких сбоев в потоках или 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 — задержка, условия).
Пример базовый:
С retryWhen для экспоненциальной задержки (backoff):
Это предотвращает "молоток" (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
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
Что выведет код?
#Tasks
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
Вопрос с собеседований
Чем отличается LinkedHashMap от HashMap?🤓
Ответ:
LinkedHashMap сохраняет порядок вставки элементов (или порядок доступа при включённом режиме accessOrder).
HashMap порядок не гарантирует.
LinkedHashMap удобен для кэшей, когда важен порядок добавления или использования.
#собеседование
Чем отличается LinkedHashMap от HashMap?
Ответ:
HashMap порядок не гарантирует.
LinkedHashMap удобен для кэшей, когда важен порядок добавления или использования.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Александр Андреевич Кузнецов (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, вопросы с собеседований - #собеседование
Предыдущий пост(с 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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Илья Алексеевич Житомирский (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
Чего ты тут забыл? 🧐
Мысли вслух, когда устаешь быть мотиватором.
И чего все лезут в 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🎶
#мои_мысли
⚠️ 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
🔥8 1
@JFB_admin_bot
пишите боту, он даст ссылку на встречу))
Общение лучше начать с команды /start
Залетайте)
пишите боту, он даст ссылку на встречу))
Общение лучше начать с команды /start
Залетайте)
👍1
gRPC и .proto.
Разбор и демонстрационный код
В сегодняшнем видео мы рассмотрели что такое gRPC.
- Написали и запустили простой демонстрационный код.
- Разобрали в чем отличие от REST, как это работает.
- Написали файл .proto, разобрали какие типы данных в нем применяются.
Как всегда немного подебажили😜
Репозиторий на GitHub ждет Ваших звезд☺️
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!✌️
Разбор и демонстрационный код
В сегодняшнем видео мы рассмотрели что такое gRPC.
- Написали и запустили простой демонстрационный код.
- Разобрали в чем отличие от REST, как это работает.
- Написали файл .proto, разобрали какие типы данных в нем применяются.
Как всегда немного подебажили
Репозиторий на GitHub ждет Ваших звезд
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Сильвио Микали (итал. 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
Коллекции в 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():
#Java #для_новичков #beginner #Collections #Set #add #remove #contains
Глава 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():
Метод 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():
Полезные советы для новичков
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
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