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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Вопрос с собеседований

Что такое Optional и зачем он нужен?🤓

Ответ:

Optional
— это контейнер, который может хранить либо значение, либо быть пустым.

Он помогает избежать NullPointerException и делает код более читаемым.

Вместо проверок if (x != null) можно использовать isPresent(), orElse(), map(), ifPresent().


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


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

Эва Тардош (венг. 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), значения могут дублироваться.

Пример кода для уникальности:
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>: Не упорядочен.


Отсортированные коллекции: Подробнее в разделе о сортировке.

Пример:
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
Что выведет код?

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
Варианты ответа:
Anonymous Quiz
17%
1
50%
2
8%
3
25%
null
👍1
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓

Голосуем за тему к рассмотрению в эти выходные!

Выбираем новую тему!

(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)

Не стесняемся! ✌️
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопрос с собеседований

Как работает Reflection API?🤓

Ответ:

Reflection API
позволяет во время выполнения анализировать и изменять классы, методы, поля и конструкторы.

Это мощный инструмент, используемый в фреймворках (например, Spring).

Однако он замедляет работу и может нарушать инкапсуляцию, поэтому применять его стоит осторожно.


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


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

Вита́лий Алекса́ндрович Я́щенко (род. 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:
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 упрощает):

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
Что выведет код?

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
Варианты ответа:
Anonymous Quiz
41%
true true
23%
false false
14%
true false
23%
false true
👍2
Вопрос с собеседований

Чем отличается checked от unchecked исключений?🤓

Ответ:

Checked
исключения наследуются от Exception и требуют обязательной обработки (try-catch или throws).

Unchecked исключения наследуются от RuntimeException и не требуют обработки.

Checked применяют для предсказуемых ошибок (например, IO), unchecked — для ошибок программиста.


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


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

Не нашел, знаете - пишите)


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

1942 — первый успешный запуск ракеты «Фау-2».


#Biography #Birth_Date #Events #03Октября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Раздел 6. Коллекции в Java

Глава 1. Введение в коллекции

(Практика):
Начать проект «Библиотека».
Создать класс Book с полями title, author, year.
Сделать список книг (пока как массив) и вывести их на экран


Перед тем, как писать код, важно правильно настроить среду разработки. Это обеспечит удобную работу и избежание ошибок на старте.

Запустите IntelliJ IDEA:
Если IDE не открыта, запустите её. Убедитесь, что у вас установлен JDK. Если проект новый, выберите "New Project" на приветственном экране.

Создайте новый проект:
В окне создания проекта выберите "Java" как тип.
Укажите имя проекта, например, "LibraryProject".
Выберите JDK в поле Project SDK (если не настроено, добавьте путь к JDK).
Оставьте остальные настройки по умолчанию (без Maven или Gradle для простоты) и нажмите "Create".
IDE создаст структуру проекта с папкой src для исходного кода.

Настройте структуру проекта:
В дереве проекта (слева) найдите src.
Если нужно, создайте пакет для организации кода: Правой кнопкой на src → New → Package → Назовите "library" (или другое имя). Это хорошая практика для группировки классов.

Создание класса Book
Теперь создадим основной класс для представления книги. Это будет простой класс с полями, который позже расширим.

Создайте класс Book:
В пакете (или прямо в src, если без пакета) щелкните правой кнопкой → New → Java Class.
Назовите класс "Book".
IDE создаст файл
Book.java с базовой структурой

public class Book {}


Добавьте поля:
В теле класса объявите три приватных поля:
title типа String (для названия книги).
author типа String (для автора).
year типа int (для года издания).


Используйте модификатор private для инкапсуляции, как мы изучали в ООП.


Добавьте конструктор:
Создайте публичный конструктор, который принимает три параметра (String title, String author, int year) и присваивает их соответствующим полям с помощью this.
Это позволит создавать объекты Book с начальными значениями.

Добавьте метод для вывода:
Создайте публичный метод, например, printDetails(), который выводит информацию о книге на экран с помощью System.out.println.
В нём используйте поля для формирования строки вроде "Название: [title], Автор: [author], Год: [year]".



Создание списка книг с использованием массива


Пока мы используем массив как простую структуру для хранения списка книг — это поможет сравнить с коллекциями позже.

Создайте класс Main:
Аналогично создайте новый класс "Main" в том же пакете.
Добавьте статический метод main(String[] args) — точку входа.


Объявите массив:
В методе main объявите массив объектов Book фиксированного размера, например, Book[] books = new Book[3]; (размер выберите небольшой для теста).

Инициализируйте массив:
Создайте несколько объектов Book с помощью new Book(title, author, year) и присвойте их элементам массива (books[0] = new Book(...); и т.д.).
Используйте разные значения для демонстрации (например, книги разных авторов и годов).


Выведите список на экран:
Используйте цикл for (или for-each: for (Book book : books)) для перебора массива.
В цикле вызовите метод printDetails() для каждого элемента, чтобы вывести информацию о книгах.


#Java #для_новичков #beginner #Collections #Практика
👍2🔥1
Тестирование и отладка проекта

После реализации протестируйте проект, чтобы убедиться, что всё работает.

Запустите проект:
Правой кнопкой на файле Main.java → Run 'Main.main()'.
В консоли IDE вы должны увидеть вывод списка книг с их деталями.


Отладка:
Если ошибки: Проверьте синтаксис (точки с запятой, скобки).
Используйте отладчик: Установите breakpoint (красная точка слева от строки в main), запустите в debug-режиме (Shift+F9) и шагайте по коду (F8).
Общие проблемы: NullPointerException (если массив не инициализирован), IndexOutOfBoundsException (если выход за пределы массива).


Проверьте вывод:
Убедитесь, что книги выводятся в порядке добавления в массив.
Попробуйте изменить размер массива или добавить больше книг — увидите, как фиксированный размер ограничивает (это мотивирует к коллекциям позже).



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

Организация кода: Используйте пакеты для группировки (например, library.models для Book).
Инкапсуляция: Даже в простом проекте делайте поля private и добавьте геттеры/сеттеры, если нужно изменять.
Массивы vs коллекции: Заметьте ограничения массива (фиксированный размер, ручное управление) — в следующих уроках заменим на ArrayList.
Комментарии: Добавляйте // комментарии к шагам, чтобы код был читаемым.
Версионирование: Если используете Git, создайте репозиторий и закоммитьте начальную версию проекта.
Ресурсы: Документация Oracle по классам и массивам для напоминания синтаксиса.



Практическое задание

Задача 1: Расширьте класс Book, добавив приватное поле isbn (String) и обновите конструктор и метод printDetails() для его включения.
Задача 2: Увеличьте массив до 5 элементов, добавьте больше книг и убедитесь, что вывод работает.
Задача 3: Попробуйте вывести только книги после определенного года — используйте if в цикле перебора массива.

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


#Java #для_новичков #beginner #Collections #Практика
👍2🔥1
Что выведет код?

import java.util.LinkedList;
import java.util.List;

public class Task031025 {
public static void main(String[] args) {
List<String> list = new LinkedList<>();
list.add("A");
list.add("B");
list.add(1, "C");
list.remove(0);
list.remove(1);
System.out.println(list);
}
}


#Tasks
🔥1
Варианты ответа:
Anonymous Quiz
0%
[A]
25%
[B]
25%
[C]
50%
IndexOutOfBoundsException
Продолжаем выбирать темы для разбора и голосовать за рассмотрение предложенных! 🤓

Голосуем за тему к рассмотрению в эти выходные!

Выбираем новую тему!

(можете предложить что-то из того, что предлагали на прошлой и позапрошлых неделях и что проиграло в голосовании!)

Не стесняемся! ✌️
Please open Telegram to view this post
VIEW IN TELEGRAM