Вопрос с собеседований
Что такое JIT-компилятор?🤓
Ответ:
JIT (Just-In-Time) — это часть JVM, которая во время выполнения переводит часто используемый байт-код в машинный код для ускорения работы.
Это позволяет сочетать переносимость байт-кода и скорость нативных программ.
JVM оптимизирует только «горячие» участки кода.
#собеседование
Что такое JIT-компилятор?
Ответ:
JIT (Just-In-Time)
Это позволяет сочетать переносимость байт-кода и скорость нативных программ.
JVM оптимизирует только «горячие» участки кода.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Джордж Садовски (родился 30 сентября 1936 года) — американский (родом из СССР) компьютерный учёный, активный продвигатель интернета в развивающихся странах; участвовал в разработке и распространении сетевой инфраструктуры, помогал реформированию законодательства и технологиям, уменьшению контроля и диверсификации доступа к интернету.
Андре́ас (Э́нди) Бе́хтольшайм (нем. Andreas Bechtolsheim; род. 30 сентября 1955, Германия, ФРГ) — немецко-американский инженер и предприниматель, сооснователь Sun Microsystems и ключевой дизайн-инженер аппаратной части; также один из первых инвесторов Google.
Иегуда Афек ( иврит : יהודה אפק ; сентябрь 1952) — израильский ученый в области компьютерных сетей, распределённых вычислений и кибербезопасности; участвовал в разработке алгоритмов устойчивости, DDoS-защиты и инфраструктурных решений интернета.
1929 — Английская служба «Би-би-си» впервые провела телетрансляцию.
1988 — года IBM объявила, что отгрузила 3-миллионный персональный компьютер PS/2.
#Biography #Birth_Date #Events #30Сентября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Знакомство с Project Reactor: Mono и Flux
Project Reactor — это не просто обёртка, а полноценный фреймворк от команды Spring, оптимизированный для производительности. Он использует неблокирующий подход: всё работает на основе событий, с минимальным потреблением ресурсов. Ключевые типы — Mono и Flux, которые воплощают потоки данных. Mono для случаев с нуля или одним элементом (как одиночный запрос), Flux для последовательностей (как стриминг). Они реализуют Publisher из Reactive Streams, так что поддерживают подписку, реакции и обратное давление.
Что такое Project Reactor и как начать?
Project Reactor — библиотека для реактивного программирования, которая строит на Reactive Streams. Она предоставляет API для создания, трансформации и потребления асинхронных потоков. Под капотом — эффективный scheduler (планировщик задач), который распределяет работу по потокам без блокировок: использует event-loop для IO и параллельные пулы для вычислений.
Чтобы начать добавьте в pom.xml (Maven):
Импортируйте:
Reactor интегрируется с Spring (WebFlux), но работает standalone. Главное преимущество: код становится декларативным — вы описываете "что" (поток и реакции), а не "как" (ожидания и циклы). Это решает callback-ад: цепочки читаемы, как последовательный код, но асинхронны.
Mono: поток для нуля или одного элемента
Mono — это тип для сценариев, где ожидается максимум один результат: успех (элемент), ошибка или ничего. Идеален для HTTP-запросов, чтения записи из БД или вычислений с одиночным исходом. Mono реализует Publisher, так что вы можете подписаться и реагировать.
Создание Mono: используйте статические методы.
- Mono.just(value): из готового значения.
- Mono.empty(): пустой поток (завершится onComplete без onNext).
- Mono.fromCallable(() -> compute()): из синхронного вызова.
- Mono.defer(() -> createMono()): ленивое создание (выполняется при подписке).
Пример простого Mono:
Асинхронный пример: симулируем задержку.
Почему Mono лучше Future/CompletableFuture?
Нет блокирующего get(): результат приходит в onNext. Нет callback-ада: цепочки через операторы (map, flatMap — разберём в следующих постах). Под нагрузкой: тысячи Mono на одном потоке, без исчерпания пула.
#Java #middle #Reactor #Reactive_Streams_API #Mono #Flux
Project Reactor — это не просто обёртка, а полноценный фреймворк от команды Spring, оптимизированный для производительности. Он использует неблокирующий подход: всё работает на основе событий, с минимальным потреблением ресурсов. Ключевые типы — Mono и Flux, которые воплощают потоки данных. Mono для случаев с нуля или одним элементом (как одиночный запрос), Flux для последовательностей (как стриминг). Они реализуют Publisher из Reactive Streams, так что поддерживают подписку, реакции и обратное давление.
Что такое Project Reactor и как начать?
Project Reactor — библиотека для реактивного программирования, которая строит на Reactive Streams. Она предоставляет API для создания, трансформации и потребления асинхронных потоков. Под капотом — эффективный scheduler (планировщик задач), который распределяет работу по потокам без блокировок: использует event-loop для IO и параллельные пулы для вычислений.
Чтобы начать добавьте в pom.xml (Maven):
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.5.0</version> <!-- версия может быть неактуальной -->
</dependency>
Импортируйте:
import reactor.core.publisher.Mono; import reactor.core.publisher.Flux;
Reactor интегрируется с Spring (WebFlux), но работает standalone. Главное преимущество: код становится декларативным — вы описываете "что" (поток и реакции), а не "как" (ожидания и циклы). Это решает callback-ад: цепочки читаемы, как последовательный код, но асинхронны.
Mono: поток для нуля или одного элемента
Mono — это тип для сценариев, где ожидается максимум один результат: успех (элемент), ошибка или ничего. Идеален для HTTP-запросов, чтения записи из БД или вычислений с одиночным исходом. Mono реализует Publisher, так что вы можете подписаться и реагировать.
Создание Mono: используйте статические методы.
- Mono.just(value): из готового значения.
- Mono.empty(): пустой поток (завершится onComplete без onNext).
- Mono.fromCallable(() -> compute()): из синхронного вызова.
- Mono.defer(() -> createMono()): ленивое создание (выполняется при подписке).
Пример простого Mono:
Mono<String> simpleMono = Mono.just("Привет из Reactor");
Подписка: subscribe() вызывает реакции.
simpleMono.subscribe(
value -> System.out.println("Значение: " + value), // onNext: реакция на элемент
error -> System.err.println("Ошибка: " + error), // onError
() -> System.out.println("Завершено") // onComplete
);
Здесь: "Значение: Привет из Reactor" и "Завершено". Подписка асинхронна — код после subscribe() идёт сразу, без ожидания. Если ошибка (например, Mono.error(new RuntimeException("Бум"))), сработает onError.
Асинхронный пример: симулируем задержку.
Mono<String> asyncMono = Mono.delay(Duration.ofSeconds(1)).map(ignore -> "Готово после секунды");
asyncMono.subscribe(System.out::println); // Вывод после 1 сек
Почему Mono лучше Future/CompletableFuture?
Нет блокирующего get(): результат приходит в onNext. Нет callback-ада: цепочки через операторы (map, flatMap — разберём в следующих постах). Под нагрузкой: тысячи Mono на одном потоке, без исчерпания пула.
#Java #middle #Reactor #Reactive_Streams_API #Mono #Flux
👍3
Flux: поток для нуля, одного или множества элементов
Flux — для последовательностей: от конечных (список) до бесконечных (стриминг). Может быть пустым, с одним элементом (как Mono) или миллионами. Flux тоже Publisher, поддерживает backpressure.
Создание Flux:
- Flux.just(a, b, c): из значений.
- Flux.fromIterable(list): из коллекции.
- Flux.range(start, count): последовательность чисел.
- Flux.interval(Duration): бесконечный таймер.
- Flux.generate(sink -> { sink.next(value); sink.complete(); }): генератор с состоянием.
Пример базового Flux:
С backpressure используйте BaseSubscriber для контроля.
Асинхронный Flux: стриминг с задержкой.
Почему Flux лучше потоков или циклов?
Масштабируемость: обрабатывает миллионы элементов без лишних ресурсов. Реактивность: реагируйте на каждый элемент, без буферов в памяти. Интеграция с обратным давлением: если подписчик медленный, Flux замедляется.
Практические советы и подводные камни
- Ленивость: Mono/Flux не выполняются без subscribe(). Полезно для отложенного вычисления.
- Ошибки: всегда обрабатывайте onError, иначе они "проглатываются".
- Блокировки: избегайте Thread.sleep() в реакциях — используйте delayElements() для асинхронных пауз.
- Тестирование: используйте StepVerifier из reactor-test: StepVerifier.create(flux).expectNext(1,2).verifyComplete();
- Камень: бесконечный Flux без take() или limitRequest() — рискуете памятью. Добавляйте .onBackpressureBuffer() или drop.
В реальной практике: в WebFlux контроллер возвращает Mono<Response> для GET, Flux<Event> для SSE (сервер-сент события).
#Java #middle #Reactor #Reactive_Streams_API #Mono #Flux
Flux — для последовательностей: от конечных (список) до бесконечных (стриминг). Может быть пустым, с одним элементом (как Mono) или миллионами. Flux тоже Publisher, поддерживает backpressure.
Создание Flux:
- Flux.just(a, b, c): из значений.
- Flux.fromIterable(list): из коллекции.
- Flux.range(start, count): последовательность чисел.
- Flux.interval(Duration): бесконечный таймер.
- Flux.generate(sink -> { sink.next(value); sink.complete(); }): генератор с состоянием.
Пример базового Flux:
Flux<Integer> numbersFlux = Flux.range(1, 5);
numbersFlux.subscribe(
value -> System.out.println("Элемент: " + value), // onNext для каждого
error -> System.err.println("Ошибка: " + error),
() -> System.out.println("Завершено")
);
Вывод: 1, 2, 3, 4, 5 и "Завершено". Асинхронно: элементы "текут" по мере готовности.
С backpressure используйте BaseSubscriber для контроля.
numbersFlux.subscribe(new BaseSubscriber<Integer>() {
@Override
protected void hookOnSubscribe(Subscription subscription) {
request(2); // Запрашиваем по 2 элемента
}
@Override
protected void hookOnNext(Integer value) {
System.out.println("Получено: " + value);
request(1); // После обработки — следующий
}
});
Это предотвращает перегрузку: Flux выдаёт элементы порциями.
Асинхронный Flux: стриминг с задержкой.
Flux<Long> tickingFlux = Flux.interval(Duration.ofMillis(500)).take(5); // 5 тиков каждые 0.5 сек
tickingFlux.subscribe(System.out::println); // 0, 1, 2, 3, 4 с паузами
Почему Flux лучше потоков или циклов?
Масштабируемость: обрабатывает миллионы элементов без лишних ресурсов. Реактивность: реагируйте на каждый элемент, без буферов в памяти. Интеграция с обратным давлением: если подписчик медленный, Flux замедляется.
Практические советы и подводные камни
- Ленивость: Mono/Flux не выполняются без subscribe(). Полезно для отложенного вычисления.
- Ошибки: всегда обрабатывайте onError, иначе они "проглатываются".
- Блокировки: избегайте Thread.sleep() в реакциях — используйте delayElements() для асинхронных пауз.
- Тестирование: используйте StepVerifier из reactor-test: StepVerifier.create(flux).expectNext(1,2).verifyComplete();
- Камень: бесконечный Flux без take() или limitRequest() — рискуете памятью. Добавляйте .onBackpressureBuffer() или drop.
В реальной практике: в WebFlux контроллер возвращает Mono<Response> для GET, Flux<Event> для SSE (сервер-сент события).
#Java #middle #Reactor #Reactive_Streams_API #Mono #Flux
👍4
Вы работали с реактивным программированием?
Anonymous Poll
4%
Да, регулярно использую!
17%
Очень редко, в особо узких местах
78%
Нет, вообще впервые слышу
Что выведет код?
#Tasks
import java.util.*;
public class Task300925 {
public static void main(String[] args) {
Set<Short> set = new HashSet<>();
for (short i = 0; i < 10; i++) {
set.add(i);
set.remove(i - 1);
}
System.out.println(set.size());
}
}
#Tasks
🔥1🤯1
Вопрос с собеседований
Что такое Optional и зачем он нужен?🤓
Ответ:
Optional — это контейнер, который может хранить либо значение, либо быть пустым.
Он помогает избежать NullPointerException и делает код более читаемым.
Вместо проверок if (x != null) можно использовать isPresent(), orElse(), map(), ifPresent().
#собеседование
Что такое Optional и зачем он нужен?
Ответ:
Optional
Он помогает избежать NullPointerException и делает код более читаемым.
Вместо проверок if (x != null) можно использовать isPresent(), orElse(), map(), ifPresent().
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Эва Тардош (венг. Tardos Éva; род. 1 октября 1957, Будапешт) — родилась 1 октября 1957 года в Будапеште. Венгерско-американский математик и специалист в теории алгоритмов, активно занимается сетевыми алгоритмами, алгоритмами потоков, теорией игр; профессор Корнелльского университета.
1967 — центральное телевидение СССР начало трансляцию программ в цветном изображении.
1982 — в Японии в продажу поступил первый коммерческий компакт-диск. Им стал альбом Билли Джоэла «52nd Street».
#Biography #Birth_Date #Events #01Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Коллекции в Java
Глава 1. Введение в коллекции
Основные характеристики коллекций: время доступа (Big O), хранение уникальных элементов, упорядоченность и сортировка
Big O (или O-нотация) — это математическая нотация, которая описывает, как растет время выполнения операции (или использование памяти) в зависимости от размера данных (n — количество элементов). Она оценивает "наихудший случай" и помогает сравнивать эффективность коллекций.
Основные обозначения Big O:
- O(1): Постоянное время — операция не зависит от размера (например, доступ по индексу в массиве).
- O(log n): Логарифмическое время — быстро растет, но эффективно (например, поиск в отсортированном дереве).
- O(n): Линейное время — пропорционально размеру (например, перебор списка).
- O(n log n): Для сортировки (например, TreeSet).
- O(n²): Квадратичное — медленно для больших n (избегайте).
Для коллекций Big O применяется к основным операциям: добавление (add), удаление (remove), поиск (contains/get), вставка.
Почему важно: Выбор коллекции влияет на производительность. Для миллионов элементов O(1) лучше O(n).
Хранение уникальных элементов
Коллекции различаются по тому, позволяют ли они дубликаты элементов.
Коллекции с уникальными элементами:
- Интерфейс Set<E>: Не позволяет дубликаты. Если добавить существующий элемент, он игнорируется (add() возвращает false).
- Пример: HashSet, TreeSet, LinkedHashSet.
- Нюанс: Уникальность определяется методом equals() и hashCode() (для HashSet). Переопределите их для custom классов.
Коллекции с дубликатами:
- Интерфейс List<E>: Позволяет дубликаты и хранит их в порядке вставки.
- Пример: ArrayList, LinkedList.
- Queue<E> и Deque<E>: Могут позволять дубликаты, в зависимости от реализации.
- Map<K, V>: Ключи уникальны (как Set), значения могут дублироваться.
Пример кода для уникальности:
- Нюанс: Для custom объектов в Set переопределите equals() и hashCode(), иначе дубликаты возможны (сравнение по ссылке).
#Java #для_новичков #beginner #Collections #BigO
Глава 1. Введение в коллекции
Основные характеристики коллекций: время доступа (Big O), хранение уникальных элементов, упорядоченность и сортировка
Big O (или O-нотация) — это математическая нотация, которая описывает, как растет время выполнения операции (или использование памяти) в зависимости от размера данных (n — количество элементов). Она оценивает "наихудший случай" и помогает сравнивать эффективность коллекций.
Основные обозначения Big O:
- O(1): Постоянное время — операция не зависит от размера (например, доступ по индексу в массиве).
- O(log n): Логарифмическое время — быстро растет, но эффективно (например, поиск в отсортированном дереве).
- O(n): Линейное время — пропорционально размеру (например, перебор списка).
- O(n log n): Для сортировки (например, TreeSet).
- O(n²): Квадратичное — медленно для больших n (избегайте).
Для коллекций Big O применяется к основным операциям: добавление (add), удаление (remove), поиск (contains/get), вставка.
Почему важно: Выбор коллекции влияет на производительность. Для миллионов элементов O(1) лучше O(n).
Хранение уникальных элементов
Коллекции различаются по тому, позволяют ли они дубликаты элементов.
Коллекции с уникальными элементами:
- Интерфейс Set<E>: Не позволяет дубликаты. Если добавить существующий элемент, он игнорируется (add() возвращает false).
- Пример: HashSet, TreeSet, LinkedHashSet.
- Нюанс: Уникальность определяется методом equals() и hashCode() (для HashSet). Переопределите их для custom классов.
Коллекции с дубликатами:
- Интерфейс List<E>: Позволяет дубликаты и хранит их в порядке вставки.
- Пример: ArrayList, LinkedList.
- Queue<E> и Deque<E>: Могут позволять дубликаты, в зависимости от реализации.
- Map<K, V>: Ключи уникальны (как Set), значения могут дублироваться.
Пример кода для уникальности:
import java.util.HashSet;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Set: Уникальные элементы
Set<String> uniqueNames = new HashSet<>();
uniqueNames.add("Алексей");
uniqueNames.add("Алексей"); // Игнорируется
System.out.println(uniqueNames.size()); // 1
// List: Дубликаты разрешены
List<String> names = new ArrayList<>();
names.add("Алексей");
names.add("Алексей");
System.out.println(names.size()); // 2
}
}
- Нюанс: Для custom объектов в Set переопределите equals() и hashCode(), иначе дубликаты возможны (сравнение по ссылке).
#Java #для_новичков #beginner #Collections #BigO
👍3
Упорядоченность элементов
Упорядоченность — это сохранение порядка элементов (по вставке или сортировке).
Коллекции с порядком вставки:
- List<E>: Всегда упорядочены по индексу (порядок добавления).
- Пример: ArrayList, LinkedList.
- LinkedHashSet<E>: Set с порядком вставки.
- LinkedHashMap<K, V>: Map с порядком вставки.
Коллекции без порядка:
- HashSet<E>: Не гарантирует порядок (зависит от хэша).
- HashMap<K, V>: Не упорядочен.
Отсортированные коллекции: Подробнее в разделе о сортировке.
Пример:
- Нюанс: Порядок в HashSet может меняться при ресайзе (rehashing), так что не полагайтесь на него.
Сортировка элементов
Сортировка — это автоматическое упорядочивание элементов по какому-то критерию (натуральный порядок или Comparator).
Отсортированные коллекции:
- SortedSet<E> (подинтерфейс Set): Уникальные, отсортированные элементы.
- Реализация: TreeSet<E> — использует красно-черное дерево.
- SortedMap<K, V> (подинтерфейс Map): Отсортированные ключи.
- Реализация: TreeMap<K, V>.
Как работает сортировка:
- Элементы должны быть Comparable<E> (метод compareTo()) для натурального порядка (числа по возрастанию, строки по алфавиту).
- Или используйте Comparator при создании: new TreeSet<>(comparator).
- Нюанс: Добавление/поиск — O(log n), так как дерево балансировано.
Пример TreeSet:
- Нюанс: TreeSet не позволяет null (NullPointerException), так как сравнивает элементы.
Для сортировки существующих коллекций используйте Collections.sort(List list) или List.sort(Comparator).
Полезные советы для новичков
- Big O в практике: Для малого n (сотни элементов) разница мала, но для миллионов — критична (выберите HashSet для быстрого contains).
- Уникальность: Set для словарей, List для списков с повторами.
- Упорядоченность: Linked* для сохранения вставки, Tree* для автосортировки.
- Сортировка: TreeSet/Map для постоянной сортировки; Collections.sort() для разовой.
- Ошибки: Null в TreeSet — NPE; дубли в Set — игнор.
- Ресурсы: Java API docs для java.util.
#Java #для_новичков #beginner #Collections #BigO
Упорядоченность — это сохранение порядка элементов (по вставке или сортировке).
Коллекции с порядком вставки:
- List<E>: Всегда упорядочены по индексу (порядок добавления).
- Пример: ArrayList, LinkedList.
- LinkedHashSet<E>: Set с порядком вставки.
- LinkedHashMap<K, V>: Map с порядком вставки.
Коллекции без порядка:
- HashSet<E>: Не гарантирует порядок (зависит от хэша).
- HashMap<K, V>: Не упорядочен.
Отсортированные коллекции: Подробнее в разделе о сортировке.
Пример:
import java.util.HashSet;
import java.util.LinkedHashSet;
public class Main {
public static void main(String[] args) {
// HashSet: Без порядка
Set<String> hashSet = new HashSet<>();
hashSet.add("Яблоко");
hashSet.add("Банан");
hashSet.add("Апельсин");
System.out.println(hashSet); // Может быть [Банан, Яблоко, Апельсин] — непредсказуемо
// LinkedHashSet: Порядок вставки
Set<String> linkedSet = new LinkedHashSet<>();
linkedSet.add("Яблоко");
linkedSet.add("Банан");
linkedSet.add("Апельсин");
System.out.println(linkedSet); // [Яблоко, Банан, Апельсин] — сохраняет порядок
}
}
- Нюанс: Порядок в HashSet может меняться при ресайзе (rehashing), так что не полагайтесь на него.
Сортировка элементов
Сортировка — это автоматическое упорядочивание элементов по какому-то критерию (натуральный порядок или Comparator).
Отсортированные коллекции:
- SortedSet<E> (подинтерфейс Set): Уникальные, отсортированные элементы.
- Реализация: TreeSet<E> — использует красно-черное дерево.
- SortedMap<K, V> (подинтерфейс Map): Отсортированные ключи.
- Реализация: TreeMap<K, V>.
Как работает сортировка:
- Элементы должны быть Comparable<E> (метод compareTo()) для натурального порядка (числа по возрастанию, строки по алфавиту).
- Или используйте Comparator при создании: new TreeSet<>(comparator).
- Нюанс: Добавление/поиск — O(log n), так как дерево балансировано.
Пример TreeSet:
import java.util.TreeSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<Integer> numbers = new TreeSet<>();
numbers.add(5);
numbers.add(1);
numbers.add(3);
System.out.println(numbers); // [1, 3, 5] — отсортировано
// Custom Comparator для обратного порядка
Set<Integer> reverseNumbers = new TreeSet<>((a, b) -> b - a);
reverseNumbers.add(5);
reverseNumbers.add(1);
reverseNumbers.add(3);
System.out.println(reverseNumbers); // [5, 3, 1]
}
}
- Нюанс: TreeSet не позволяет null (NullPointerException), так как сравнивает элементы.
Для сортировки существующих коллекций используйте Collections.sort(List list) или List.sort(Comparator).
Полезные советы для новичков
- Big O в практике: Для малого n (сотни элементов) разница мала, но для миллионов — критична (выберите HashSet для быстрого contains).
- Уникальность: Set для словарей, List для списков с повторами.
- Упорядоченность: Linked* для сохранения вставки, Tree* для автосортировки.
- Сортировка: TreeSet/Map для постоянной сортировки; Collections.sort() для разовой.
- Ошибки: Null в TreeSet — NPE; дубли в Set — игнор.
- Ресурсы: Java API docs для java.util.
#Java #для_новичков #beginner #Collections #BigO
👍3
Что выведет код?
#Tasks
import java.util.*;
public class Task011025 {
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
((LinkedList<Integer>) queue).removeLast();
queue.poll();
System.out.println(queue.peek());
}
}
#Tasks
👍1
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!✌️
Голосуем за тему к рассмотрению в эти выходные!
Выбираем новую тему!
(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)
Не стесняемся!
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопрос с собеседований
Как работает Reflection API?🤓
Ответ:
Reflection API позволяет во время выполнения анализировать и изменять классы, методы, поля и конструкторы.
Это мощный инструмент, используемый в фреймворках (например, Spring).
Однако он замедляет работу и может нарушать инкапсуляцию, поэтому применять его стоит осторожно.
#собеседование
Как работает Reflection API?
Ответ:
Reflection API
Это мощный инструмент, используемый в фреймворках (например, Spring).
Однако он замедляет работу и может нарушать инкапсуляцию, поэтому применять его стоит осторожно.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1 1
Вита́лий Алекса́ндрович Я́щенко (род. 2 октября 1941, Пятигорск, Ставропольский край) — родился 2 октября 1941 в Пятигорске. Украинский (раньше — советский) ученый-кибернетик, создатель нового класса нейроподобных растущих сетей.
Гай Льюис Стил-младший (/ s t iː l / ; родился 2 октября 1954 года) — американский компьютерный учёный, родился 2 октября 1954. Внёс значительный вклад в проектирование языков программирования и стандарты.
Ве́рнор Сти́вен Ви́ндж (англ. Vernor Steffen Vinge, о файле/ˈvɜːrnər ˈvɪndʒiː/; 2 октября 1944, Уокешо, Висконсин — 20 марта 2024, Ла-Холья, Калифорния) — родился 2 октября 1944. Американский учёный-информатик и писатель, сформулировал идеи технологической сингулярности и внес вклад в теорию вычислений и футуризм.
1991 — компьютерные гиганты Apple, IBM и Motorola договорились о создании альянса, направленного прежде всего против Microsoft, для создания платформы PReP.
2002 — в Японии в продажу поступил первый в мире робот-инкассатор.
#Biography #Birth_Date #Events #02Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Реактивное программирование
Подписка и жизненный цикл в Reactor: onNext, onError, onComplete
Reactor делает код декларативным — вы описываете поток событий, а не управляете ожиданиями вручную.
Но чтобы потоки "ожили", нужна подписка: это момент, когда издатель начинает передавать данные, а подписчик реагирует. Подписка и жизненный цикл в Reactor - это фундамент: без понимания, как срабатывают onNext (реакция на элемент), onError (обработка ошибки) и onComplete (завершение), ваши реактивные конвейеры останутся мёртвыми.
Представьте жизненный цикл как этапы реки: подписка — запуск потока, onNext — течение воды, onError — буря, onComplete — устье.
Подписка — это связь между издателем (Publisher, как Mono/Flux) и подписчиком (Subscriber). Она запускает поток данных асинхронно, без блокировок. Жизненный цикл определяет порядок событий: от старта до конца или ошибки. Это решает проблемы из первого поста — вместо callback-ада и ручных get(), вы получаете структурированные реакции. Всё построено на Reactive Streams API, с обратным давлением.
Подписка: запуск потока данных
В Reactor Mono или Flux — ленивые: они ничего не делают, пока не подпишетесь. Метод subscribe() — это триггер: он регистрирует подписчика и начинает передавать события (push, из поста 3).
Подписка асинхронна: после subscribe() код продолжается сразу, без ожидания завершения.
Базовые варианты subscribe():
subscribe(): без параметров — данные "проглатываются", но поток запускается. Полезно для fire-and-forget (запустил и забыл).
subscribe(Consumer<T> onNext): только реакция на элементы.
subscribe(Consumer<T> onNext, Consumer<Throwable> onError): плюс обработка ошибок.
subscribe(Consumer<T> onNext, Consumer<Throwable> onError, Runnable onComplete): полный цикл.
subscribe(Subscriber<T> subscriber): кастомный подписчик для полного контроля (с onSubscribe для Subscription).
Пример простейшей подписки на Flux:
Почему это лучше традиционных? В CompletableFuture вы цепляете thenApply/thenAccept, но рискуете вложенностью. В Reactor subscribe() — точка входа, а реакции — в одном месте. Плюс, подписка возвращает Disposable: объект для отмены (dispose()) в любой момент.
Пример:
#Java #middle #Reactor #Reactive_Streams_API #onNext #onError #onComplet
Подписка и жизненный цикл в Reactor: onNext, onError, onComplete
Reactor делает код декларативным — вы описываете поток событий, а не управляете ожиданиями вручную.
Но чтобы потоки "ожили", нужна подписка: это момент, когда издатель начинает передавать данные, а подписчик реагирует. Подписка и жизненный цикл в Reactor - это фундамент: без понимания, как срабатывают onNext (реакция на элемент), onError (обработка ошибки) и onComplete (завершение), ваши реактивные конвейеры останутся мёртвыми.
Представьте жизненный цикл как этапы реки: подписка — запуск потока, onNext — течение воды, onError — буря, onComplete — устье.
Подписка — это связь между издателем (Publisher, как Mono/Flux) и подписчиком (Subscriber). Она запускает поток данных асинхронно, без блокировок. Жизненный цикл определяет порядок событий: от старта до конца или ошибки. Это решает проблемы из первого поста — вместо callback-ада и ручных get(), вы получаете структурированные реакции. Всё построено на Reactive Streams API, с обратным давлением.
Подписка: запуск потока данных
В Reactor Mono или Flux — ленивые: они ничего не делают, пока не подпишетесь. Метод subscribe() — это триггер: он регистрирует подписчика и начинает передавать события (push, из поста 3).
Подписка асинхронна: после subscribe() код продолжается сразу, без ожидания завершения.
Базовые варианты subscribe():
subscribe(): без параметров — данные "проглатываются", но поток запускается. Полезно для fire-and-forget (запустил и забыл).
subscribe(Consumer<T> onNext): только реакция на элементы.
subscribe(Consumer<T> onNext, Consumer<Throwable> onError): плюс обработка ошибок.
subscribe(Consumer<T> onNext, Consumer<Throwable> onError, Runnable onComplete): полный цикл.
subscribe(Subscriber<T> subscriber): кастомный подписчик для полного контроля (с onSubscribe для Subscription).
Пример простейшей подписки на Flux:
import reactor.core.publisher.Flux;
Flux<String> fruitsFlux = Flux.just("яблоко", "банан", "вишня");
fruitsFlux.subscribe(
fruit -> System.out.println("Съедено: " + fruit), // onNext: реакция на каждый элемент
error -> System.err.println("Проблема: " + error.getMessage()), // onError: если ошибка
() -> System.out.println("Фрукты закончились") // onComplete: завершение
);
Вывод: "Съедено: яблоко", "Съедено: банан", "Съедено: вишня", "Фрукты закончились". Если добавить ошибку — Flux.just("яблоко").concatWith(Flux.error(new RuntimeException("Гнилой фрукт"))) — сработает onError, и onComplete не вызовется.
Почему это лучше традиционных? В CompletableFuture вы цепляете thenApply/thenAccept, но рискуете вложенностью. В Reactor subscribe() — точка входа, а реакции — в одном месте. Плюс, подписка возвращает Disposable: объект для отмены (dispose()) в любой момент.
Пример:
Disposable disposable = fruitsFlux.subscribe(...);
disposable.dispose(); // Отмена: поток остановится, onComplete не сработает.
Это полезно для UI или долгоживущих потоков: отпишись, когда компонент уничтожен, чтобы избежать утечек памяти.
#Java #middle #Reactor #Reactive_Streams_API #onNext #onError #onComplet
👍2
Жизненный цикл: этапы от старта до финиша
Жизненный цикл в Reactive Streams — последовательность вызовов: onSubscribe → (onNext)* → (onError | onComplete). Это правило: после onError или onComplete ничего не будет, и поток считается завершённым.
onSubscribe(Subscription s): первый вызов после subscribe(). Здесь подписчик получает Subscription для контроля (request(n) для backpressure или cancel()). Без request() данные не потекут — это защита от перегрузки.
onNext(T item): для каждого элемента. Здесь основная логика: обработка, логирование, трансформация. Может вызываться много раз (в Flux) или раз/никогда (в Mono).
Важно: держите onNext быстрым и неблокирующим — если медленный, перенесите на отдельный планировщик (Schedulers).
onError(Throwable t): если ошибка (исключение). Поток прерывается, onComplete не сработает. Обработайте, чтобы не потерять: логируйте, retry (повторите) или fallback (запасной вариант).
onComplete(): успешное завершение. Нет элементов после, но сигнал, что всё ок.
Пример полного цикла с кастомным подписчиком (BaseSubscriber в Reactor упрощает):
Обработка ошибок и завершения: стратегии для устойчивости
Ошибки — часть жизни: сеть упала, БД не ответила. В Reactor onError — ваш щит. Не игнорируйте: используйте операторы для восстановления.
doOnError(Consumer<Throwable>): дополнительная реакция перед onError подписчика.
onErrorReturn(T value): fallback — верни значение вместо ошибки.
onErrorResume(Function<Throwable, Publisher<T>>): замени на другой поток.
retry(long times): повтори попытку.
Пример с восстановлением:
Практические советы и подводные камни
Всегда реализуйте все методы в Subscriber: иначе дефолтные могут "проглотить" ошибки (onError кидает RuntimeException, если не переопределён).
Используйте Hooks: doOnSubscribe, doOnNext для логирования без изменения потока.
Отмена: dispose() не гарантирует мгновенную остановку — upstream (источник) может продолжить, но данные не дойдут.
Камень: в onNext избегайте блокировок (sleep, IO) — используйте publishOn(Schedulers.boundedElastic()) для переноса.
Тестирование: StepVerifier.create(flux).expectSubscription().expectNext(1,2).expectError().verify(); — проверяет цикл.
В практике: в WebFlux сервис возвращает Flux, клиент subscribe() в контроллере — реакции на события в реальном времени.
#Java #middle #Reactor #Reactive_Streams_API #onNext #onError #onComplet
Жизненный цикл в Reactive Streams — последовательность вызовов: onSubscribe → (onNext)* → (onError | onComplete). Это правило: после onError или onComplete ничего не будет, и поток считается завершённым.
onSubscribe(Subscription s): первый вызов после subscribe(). Здесь подписчик получает Subscription для контроля (request(n) для backpressure или cancel()). Без request() данные не потекут — это защита от перегрузки.
onNext(T item): для каждого элемента. Здесь основная логика: обработка, логирование, трансформация. Может вызываться много раз (в Flux) или раз/никогда (в Mono).
Важно: держите onNext быстрым и неблокирующим — если медленный, перенесите на отдельный планировщик (Schedulers).
onError(Throwable t): если ошибка (исключение). Поток прерывается, onComplete не сработает. Обработайте, чтобы не потерять: логируйте, retry (повторите) или fallback (запасной вариант).
onComplete(): успешное завершение. Нет элементов после, но сигнал, что всё ок.
Пример полного цикла с кастомным подписчиком (BaseSubscriber в Reactor упрощает):
import reactor.core.publisher.BaseSubscriber;
Flux<Integer> numbersFlux = Flux.range(1, 10).map(i -> {
if (i == 5) throw new RuntimeException("Ошибка на 5"); // Симулируем ошибку
return i;
});
numbersFlux.subscribe(new BaseSubscriber<Integer>() {
@Override
protected void hookOnSubscribe(Subscription subscription) {
System.out.println("Подписка готова");
request(3); // Запрашиваем первые 3
}
@Override
protected void hookOnNext(Integer value) {
System.out.println("Элемент: " + value);
request(1); // Запрашиваем по одному дальше
}
@Override
protected void hookOnError(Throwable throwable) {
System.err.println("Ошибка: " + throwable.getMessage());
}
@Override
protected void hookOnComplete() {
System.out.println("Цикл завершён");
}
});
Вывод: "Подписка готова", "Элемент: 1", "Элемент: 2", "Элемент: 3", "Элемент: 4", "Ошибка: Ошибка на 5". onComplete не сработает, потому что ошибка. Без ошибки — все 10 элементов и "Цикл завершён".
Это демонстрирует контроль: request() управляет темпом, как в backpressure (пост 5). Если не request() — только "Подписка готова".
Обработка ошибок и завершения: стратегии для устойчивости
Ошибки — часть жизни: сеть упала, БД не ответила. В Reactor onError — ваш щит. Не игнорируйте: используйте операторы для восстановления.
doOnError(Consumer<Throwable>): дополнительная реакция перед onError подписчика.
onErrorReturn(T value): fallback — верни значение вместо ошибки.
onErrorResume(Function<Throwable, Publisher<T>>): замени на другой поток.
retry(long times): повтори попытку.
Пример с восстановлением:
Mono<String> riskyMono = Mono.fromCallable(() -> {
if (Math.random() > 0.5) throw new RuntimeException("Сбой");
return "Успех";
}).onErrorReturn("Fallback").retry(2); // Retry 2 раза
riskyMono.subscribe(
System.out::println,
error -> System.out.println("Не удалось: " + error),
() -> System.out.println("Завершено")
);
Если сбой — retry, потом fallback. onComplete сработает только при успехе или fallback.
Для onComplete: используйте doFinally(Runnable) — сработает всегда, после onComplete или onError. Полезно для закрытия ресурсов: doFinally(() -> connection.close()).
Практические советы и подводные камни
Всегда реализуйте все методы в Subscriber: иначе дефолтные могут "проглотить" ошибки (onError кидает RuntimeException, если не переопределён).
Используйте Hooks: doOnSubscribe, doOnNext для логирования без изменения потока.
Отмена: dispose() не гарантирует мгновенную остановку — upstream (источник) может продолжить, но данные не дойдут.
Камень: в onNext избегайте блокировок (sleep, IO) — используйте publishOn(Schedulers.boundedElastic()) для переноса.
Тестирование: StepVerifier.create(flux).expectSubscription().expectNext(1,2).expectError().verify(); — проверяет цикл.
В практике: в WebFlux сервис возвращает Flux, клиент subscribe() в контроллере — реакции на события в реальном времени.
#Java #middle #Reactor #Reactive_Streams_API #onNext #onError #onComplet
👍2
Что выведет код?
#Tasks
import java.util.*;
public class Task021025 {
public static void main(String[] args) {
Map<String, Integer> map1 = new HashMap<>();
Map<String, Integer> map2 = new HashMap<>();
map1.put("a", 1);
map1.put("b", 1);
map2.put("b", 1);
map2.put("a", 1);
System.out.println(map1.equals(map2));
System.out.println(Objects.equals(map1, map2));
}
}
#Tasks
👍1
👍2