Java for Beginner
870 subscribers
1.01K photos
275 videos
14 files
1.69K links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
С 14.03 по 20.03
Предыдущий пост(с 07.03 по 13.03)

Воскресный мотивационный пост:
Не было мотивации, а вообще нужна?) (все равно это никто не читает)

Запись встреч/видео:
Видео в процессе подготовки... lvl2

Обучающие статьи:
Раздел 8. Stream API и функциональный стиль

Глава 5: Контракты. Почему equals, hashCode и иммутабельность — закон
(Практика): Саботаж и починка в «Библиотеке»

Глава 6: Parallel Stream
Механика ForkJoinPool.commonPool()
Условия эффективности параллельного stream

[Совет по Java #016]
Тема: Ленивая загрузка в Hibernate (FetchType.LAZY) не работает после закрытия сессии.

[Совет по Java #017]
Тема: ConcurrentModificationException при итерации и модификации коллекции


Полезные статьи и видео:
WebFlux, Virtual Threads и все-все-все

Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍4🔥1
🤣4
🤣4
Потратил 6! часов, чтобы собрать настройки ретраев и CircuitBreaker в resilience4j в полноценно работающую демонстрацию...

И все для вас)))🧑‍💻

Скоро будет видео 💃
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍3🍾11
2😱1
История технологий сегодня — 22 марта

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

Ро́берт Э́ндрюс Ми́лликен (англ. Robert Andrews Millikan; 22 марта 1868, Моррисон, Иллинойс, США — 19 декабря 1953, Сан-Марино, Калифорния, США) — американский физик. В 1923 году получил Нобелевскую премию по физике за работы в области фотоэлектрического эффекта и за измерения заряда электрона[4]. Впоследствии он занимался изучением космических лучей.

Бертон Ри́хтер (англ. Burton Richter; 22 марта 1931, Нью-Йорк, США — 18 июля 2018, Станфорд, штат Калифорния, США) американский физик, лауреат Нобелевской премии по физике в 1976 году, совместно с Самюэлем Тингом «за основополагающий вклад в работу по открытию тяжёлой элементарной частицы нового типа».


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

1895 — в Париже состоялась первая в истории публичная демонстрация кинофильма. Это был фильм братьев Люмьер «Выход рабочих с фабрики».

1902 — Британия и Персия заключили договор о соединении телеграфной линией Европы и Индии.


1904 — в лондонской газете «Иллюстрейтед Миррор» впервые в мире опубликована цветная фотография.


#Biography #Birth_Date #Events #22марта
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
9. Retry vs Circuit Breaker: кто спасёт ваши сервисы от каскадных падений?

В этом видео мы на реальном примере разберём, как правильно комбинировать Retry и Circuit Breaker с помощью Resilience4j, чтобы сделать систему устойчивой к сбоям внешних зависимостей.

Что вас ждёт:

🔵 Retry — когда он полезен, а когда опасен.
🔵 Circuit Breaker — как он работает, зачем нужны состояния CLOSED, OPEN, HALF-OPEN и как его настраивать.
🔵 Разбор настройки через application.yml: скользящие окна, пороги ошибок, медленные вызовы, экспоненциальный backoff.
🔵 Сравнение Spring Retry и Resilience4j: что выбрать для production?
🔵 Готовые фрагменты кода и конфигурации для внедрения в ваш проект.

Исходный код проекта на GitHub очень ждет Ваших звезд ☺️

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

Смотрите, ставьте лайки, подписывайтесь на каналы!✌️

❗️❗️❗️ Огромная просьба - если Вам понравилась моя работа, распространите эту серию по всем доступным вам местам: телеграм, discord и прочим каналам. ❗️❗️❗️

Буду крайне благодарен
🙂
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
История технологий сегодня — 23 марта

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

Джин Э. Саммет (23 марта 1928 — 20 мая 2017) — американская учёная в области информатики, разработавшая язык программирования FORMAC в 1962 году. Она также была одним из разработчиков влиятельного языка программирования COBOL.

Вернер Магнус Максимилиан фрайхерр фон Браун (нем. Wernher Magnus Maximilian Freiherr von Braun; 23 марта 1912, Вирзиц, провинция Позен, Пруссия, Германская империя — 16 июня 1977, Александрия, Виргиния, США)германский, а с 1955 года — американский конструктор ракетно-космической техники, один из основоположников современного ракетостроения, создатель первых баллистических ракет. Член НСДАП с 1937 года, штурмбаннфюрер СС (1943—1945). В США считается отцом американской космической программы.


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

1876 — русский инженер Павел Яблочков запатентовал электрическую лампочку.

1983 — запущен «Астрон», советский космический ультрафиолетовый телескоп.

2020 — компания Valve выпустила компьютерную игру для устройств виртуальной реальности «Half-Life: Alyx» (на Windows) *Кто не играл - рекомендую


#Biography #Birth_Date #Events #23марта
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Раздел 8. Stream API и функциональный стиль в Java

Глава 6: Parallel Stream

Гонка параллельных stream в «Библиотеке»

Подготовка: расширение модели Book

Добавьте поле для имитации дорогой операции:
public class Book {
private final String title;
private final String author;
private final int year;
private final List<String> genres;
private final int complexity; // «сложность» проверки, влияет на время фильтрации

public Book(String title, String author, int year,
List<String> genres, int complexity) {
this.title = title;
this.author = author;
this.year = year;
this.genres = genres;
this.complexity = complexity;
}

// геттеры...

public boolean isExpensiveFantasyCheck() {
// Имитация дорогой операции: чем выше complexity, тем дольше
try {
Thread.sleep(complexity); // миллисекунды
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return genres.contains("Фантастика");
}
}



Базовый эксперимент: поиск фантастики

Метод для измерения
public class ParallelStreamBenchmark {

public static List<String> findFantasyTitlesSequential(List<Book> books) {
return books.stream()
.filter(Book::isExpensiveFantasyCheck)
.map(Book::getTitle)
.collect(Collectors.toList());
}

public static List<String> findFantasyTitlesParallel(List<Book> books) {
return books.parallelStream()
.filter(Book::isExpensiveFantasyCheck)
.map(Book::getTitle)
.collect(Collectors.toList());
}

public static long measure(Runnable task) {
long start = System.nanoTime();
task.run();
long end = System.nanoTime();
return (end - start) / 1_000_000; // миллисекунды
}
}



Три сценария: малые, средние, большие данные

Сценарий А: 10 элементов, лёгкая операция (complexity = 0)

List<Book> tinyLibrary = IntStream.range(0, 10)
.mapToObj(i -> new Book("Книга " + i, "Автор " + i,
2000 + i, Arrays.asList(i % 2 == 0 ? "Фантастика" : "Роман"), 0))
.collect(Collectors.toList());

long seqTime = measure(() -> findFantasyTitlesSequential(tinyLibrary));
long parTime = measure(() -> findFantasyTitlesParallel(tinyLibrary));

System.out.println("10 элементов, лёгкая операция:");
System.out.println(" Последовательно: " + seqTime + " мс");
System.out.println(" Параллельно: " + parTime + " мс");
System.out.println(" Накладка: " + (parTime - seqTime) + " мс");


Ожидаемый результат: Параллельная версия медленнее в 2–10 раз.

Почему:
Разбиение потока на сегменты (splitting)
Передача задач в ForkJoinPool
Синхронизация при сборке результата (ConcurrentHashMap для toList)
Координация потоков дороже, чем сама работа

Сценарий Б: 10 000 элементов, лёгкая операция
List<Book> mediumLibrary = IntStream.range(0, 10_000)
.mapToObj(i -> new Book("Книга " + i, "Автор " + i,
2000 + i % 100,
Arrays.asList(i % 3 == 0 ? "Фантастика" : "Роман"), 0))
.collect(Collectors.toList());

// те же измерения


Ожидаемый результат: Примерно паритет или лёгкий проигрыш параллельной версии.

Почему:
Накладка на координацию амортизируется
Но операция всё ещё слишком лёгкая — переключение контекста не окупается

Сценарий В: 100 000 элементов, тяжёлая операция (complexity = 1 мс)
List<Book> largeLibrary = IntStream.range(0, 100_000)
.mapToObj(i -> new Book("Книга " + i, "Автор " + i,
2000 + i % 100,
Arrays.asList(i % 3 == 0 ? "Фантастика" : "Роман"), 1))
.collect(Collectors.toList());

// те же измерения


Ожидаемый результат: Параллельная версия быстрее в 2–4 раза (на многоядерной машине).

Почему:
Общая работа: 100 000 × 1 мс = 100 секунд последовательно
На 8 ядрах: теоретически ~12.5 секунд + накладка
Накладка амортизируется на большом объёме вычислений


#Java #для_новичков #beginner #stream_api #ForkJoinPool #parallelStream #практика
👍3🔥1
Проблема с неправильными источниками

Демонстрация: LinkedList vs ArrayList

List<Book> arrayList = new ArrayList<>(largeLibrary);
List<Book> linkedList = new LinkedList<>(largeLibrary);

// ArrayList — хорошее разбиение
long arrayListParallel = measure(() ->
arrayList.parallelStream().filter(...).collect(...));

// LinkedList — плохое разбиение
long linkedListParallel = measure(() ->
linkedList.parallelStream().filter(...).collect(...));

System.out.println("ArrayList parallel: " + arrayListParallel + " мс");
System.out.println("LinkedList parallel: " + linkedListParallel + " мс");


Ожидаемый результат: LinkedList в 3–10 раз медленнее из-за невозможности эффективного разбиения.


Интеграция в проект «Библиотеке»


Задача: параллельный анализ большой библиотеки

Добавьте в Library метод для статистики с тяжёлыми вычислениями:
public Map<String, Double> analyzeGenreComplexityParallel() {
return books.parallelStream()
.collect(Collectors.groupingByConcurrent(
book -> book.getGenres().get(0), // основной жанр
Collectors.averagingInt(Book::getComplexity)
));
}


Сравните с последовательной версией на 100 000 книгах.


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

Задача 1: неправильное использование

Напишите код, который демонстрирует проблемы:
parallelStream().forEach(System.out::println) — беспорядок в выводе
parallelStream().sorted() — избыточная синхронизация
parallelStream() для записи в общий StringBuilder — race condition
Объясните, почему каждый случай ломается.

Задача 2: правильный кастомный коллектор (звёздочка)

Реализуйте parallelStream-совместимый коллектор для Map<Author, List<Book>>, который:
Использует ConcurrentHashMap для аккумулятора
Корректно обрабатывает combiner для слияния частичных результатов
Сохраняет порядок книг внутри автора
Сравните производительность с groupingByConcurrent.

#Java #для_новичков #beginner #stream_api #ForkJoinPool #parallelStream #практика
👍4🔥1
Что выведет код?

import java.util.*;

public class Task230326 {
public static void main(String[] args) {
TreeSet<String> set = new TreeSet<>();
set.add("apple");
set.add("banana");
System.out.println(set.contains(null));
}
}


#Tasks
👍2
👍2
Что такое varargs (variable arguments)? 🤓

Ответ:

Varargs (синтаксис ...)
позволяет передавать в метод произвольное количество аргументов одного типа.

Объявляется как void method(String... args). Внутри метода аргументы обрабатываются как массив.

Varargs-параметр должен быть последним в списке параметров метода.

Это удобная альтернатива передаче массива — можно вызывать метод как method("a", "b", "c"), так и method() (с пустым массивом).


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологий сегодня — 24 марта

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

Серге́й Ива́нович Вави́лов (12 [24] марта 1891, Москва — 25 января 1951, там же) — советский физик, основатель научной школы физической оптики в СССР, общественный деятель и популяризатор науки; младший брат генетика Николая Вавилова. Президент Академии наук СССР (с 1945; действительный член с 1932), лауреат четырёх Сталинских премий. Соавтор (наряду со своими учеником Павлом Черенковым и коллегами Игорем Таммом и Ильёй Франком) открытия и истолкования эффекта Вавилова — Черенкова.


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

1802 — английский изобретатель Ричард Тревитик получил первый патент на паровоз.

1930 — карликовая планета Плутон получает своё нынешнее имя.

2001 — выход первого релиза Mac OS X (Гепард).


#Biography #Birth_Date #Events #24марта
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
[Совет по Java #018]

Тема: Анонимные классы и лямбды захватывают переменные. Если переменная используется внутри, она должна быть effectively final. Нельзя менять ее значение внутри лямбды.

Проблема: Лямбда-выражения и анонимные классы захватывают (capture) переменные из объемлющего контекста.

Для обеспечения согласованности и предотвращения проблем с многопоточностью Java требует, чтобы такие переменные были effectively final — то есть не изменялись после инициализации. Попытка изменить захваченную переменную внутри лямбды или передать в лямбду переменную, которая изменяется где-то еще, приводит к ошибке компиляции.

Это ограничение связано с тем, что лямбда может выполняться в другом потоке, и изменение внешней переменной создало бы состояние гонки (race condition).

Решение: Используйте обертку (массив, AtomicReference, или поле класса) для "модифицируемых" переменных, если модификация необходима.

Однако лучше пересмотреть дизайн: для накопления результатов используйте Stream API (reduce, collect) или вынесите логику в отдельный метод. Для счетчиков внутри лямбды применяйте AtomicInteger или объекты-контейнеры.

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.*;

public class LambdaCaptureExample {

public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

//Ошибка: переменная не effectively final
int count = 0;
// names.forEach(name -> count++); // Compilation error!

//Ошибка: передача изменяемой переменной
int threshold = 5;
// threshold = 10;
// names.stream().filter(name -> name.length() > threshold); // Ошибка! threshold изменился

//Решение 1: AtomicInteger для счетчика
AtomicInteger counter = new AtomicInteger(0);
names.forEach(name -> {
if (name.length() > 3) {
counter.incrementAndGet(); // Безопасно
}
});
System.out.println("Count > 3: " + counter.get());

//Решение 2: Использование Stream API вместо накопления
long streamCount = names.stream()
.filter(name -> name.length() > 3)
.count(); // Никаких захваченных переменных
System.out.println("Stream count: " + streamCount);

//Решение 3: Массив как контейнер
int[] arrayCount = {0};
names.forEach(name -> {
if (name.length() > 3) {
arrayCount[0]++; // Работает, но менее элегантно
}
});
System.out.println("Array count: " + arrayCount[0]);

//Антипаттерн: сложный захват
for (int i = 0; i < 3; i++) {
// i меняется, нельзя использовать в лямбде
// new Thread(() -> System.out.println(i)).start(); // Ошибка!

//Правильно: копия значения
int index = i;
new Thread(() -> System.out.println("Index: " + index)).start();
}

// Пример с effectively final
String prefix = "User: "; // effectively final
names.stream()
.map(name -> prefix + name) // Работает
.forEach(System.out::println);

// prefix = "Person: "; // Раскомментируй — ошибка!
}
}


Объяснение: Понятие "effectively final" было введено в Java 8. Переменная считается effectively final, если ее значение не изменяется после инициализации.

Лямбды и анонимные классы не могут изменять локальные переменные, так как они хранятся на стеке, а лямбда может быть выполнена после выхода из метода (например, в другом потоке). Использование оберток (AtomicInteger, массивы) работает, потому что ссылка на объект-контейнер effectively final, а изменяется внутреннее состояние объекта. Однако это неидиоматично.

#Java #советы
👍6
Что выведет код?

import java.util.function.Consumer;

public class Task240326 {
public static void main(String[] args) {
int[] counter = {0};

Consumer<String> processor = s -> {
counter[0]++;
System.out.print(s + counter[0] + " ");
};

for (int i = 0; i < 3; i++) {
processor.accept("A");
}

System.out.println(counter[0]);
}
}


#Tasks
👍4
👍2
В чем разница между break и continue? 🤓

Ответ:

Оба оператора используются для управления потоком выполнения в циклах.

break полностью завершает выполнение цикла, в котором он находится, и передает управление на следующую за циклом инструкцию.

continue прерывает только текущую итерацию цикла и переходит к следующей итерации (проверке условия для следующего шага).

В циклах for continue выполняет инкремент/декремент, в while и do-while переходит сразу к проверке условия.


#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологий сегодня — 25 марта

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

Христофо́р Кла́виус (или Клавий, лат. Christophorus Clavius; 25 марта 1538, Бамберг — 6 февраля 1612, Рим) — немецкий математик и астроном. Член ордена иезуитов. Известен как главный разработчик окончательной версии современного григорианского календаря. В последние годы своей жизни был одним из самых уважаемых астрономов в Европе, а его книги по астрономии широко использовались более 50 лет. Множество видных европейских астрономов и математиков обучались у Клавиуса, среди них: Грегуар де Сен-Венсан, Марин Гетальдич, Джулио Алени и Пауль Гульдин.

Кейси Оуэн Нейстат (родился 25 марта 1981 г.) — американский YouTube-блогер , кинорежиссер , видеоблогер и соучредитель мультимедийной компании Beme , которая позже была приобретена CNN. В 2018 году он основал 368, креативное пространство для сотрудничества создателей.

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

1938 — Трансляцией фильма «Великий гражданин» начато регулярное вещание Московского телецентра.

1995 — Уорд Каннингем сделал общедоступной WikiWikiWeb, первую в мире вики-систему, являющуюся частью Портлендского репозитория шаблонов.


#Biography #Birth_Date #Events #25марта
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 8. Stream API и функциональный стиль в Java

Глава 7: Stream API в экосистеме Java. Интеграционные паттерны

Примитивные стримы (IntStream, LongStream)

Одно из фундаментальных ограничений Java — отсутствие обобщений (generics) для примитивных типов. Stream<T> может содержать только ссылочные типы, что вынуждает упаковывать int в Integer, long в Long, double в Double. Эта операция, называемая боксингом (boxing), создаёт объекты-обёртки в куче, увеличивает нагрузку на GC и снижает производительность кэша процессора из-за разыменования указателей.

Примитивные стримы — IntStream, LongStream, DoubleStream — решают эту проблему через специализацию. Они работают с сырыми примитивами, избегая аллокаций и обеспечивая плотное размещение данных в памяти.


Генерация числовых последовательностей

range и rangeClosed

IntStream.range(start, end) генерирует последовательность от start (включительно) до end (исключительно). rangeClosed включает обе границы.
// Индексы для обхода: 0, 1, 2, ..., 99
IntStream indices = IntStream.range(0, 100);

// Дни месяца: 1, 2, ..., 31
IntStream days = IntStream.rangeClosed(1, 31);


Эти методы возвращают упорядоченные, конечные потоки с известным размером — оптимальные характеристики для параллелизма. Spliterator такого потока делится идеально: середина вычисляется как (start + end) >>> 1, создавая сбалансированные сегменты.

iterate и generate

Бесконечные последовательности создаются через iterate (с заданным началом и функцией следующего элемента) или generate (с поставщиком значений).
// Степени двойки: 1, 2, 4, 8, ... с ограничением
IntStream powersOfTwo = IntStream.iterate(1, n -> n * 2)
.limit(20);

// Случайные числа
IntStream randomInts = new Random().ints(); // Бесконечный
IntStream limitedRandom = new Random().ints(100, 0, 1000); // 100 чисел от 0 до 999


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


Spliterator.

Агрегация примитивов: статистика без промежуточных объектов

Примитивные стримы предоставляют терминальные операции, возвращающие примитивные значения без боксинга:
int sum = IntStream.range(1, 101).sum();  // 5050, возвращает int

long count = LongStream.range(0, 1_000_000).count(); // 1000000L

OptionalDouble average = IntStream.of(10, 20, 30).average(); // OptionalDouble[20.0]

OptionalInt max = IntStream.of(3, 1, 4, 1, 5).max(); // OptionalInt[5]
OptionalInt, OptionalLong, OptionalDouble — примитивные версии Optional, избегающие обёртки. Методы: isPresent(), getAsInt() / getAsLong() / getAsDouble(), orElse(int), orElseGet(IntSupplier).


summaryStatistics: комплексная агрегация

Для многократной статистики за один проход:
IntSummaryStatistics stats = IntStream.of(10, 20, 30, 40, 50)
.summaryStatistics();

System.out.println(stats.getCount()); // 5
System.out.println(stats.getSum()); // 150
System.out.println(stats.getMin()); // 10
System.out.println(stats.getMax()); // 50
System.out.println(stats.getAverage()); // 30.0


IntSummaryStatistics — mutable контейнер, накапливающий данные без промежуточных коллекций. Эффективен для больших потоков: вместо boxed().collect(summarizingInt(Integer::intValue)) используется прямая агрегация примитивов.


#Java #для_новичков #beginner #stream_api #IntStream #LongStream
👍5