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

import java.util.ArrayList;
import java.util.List;

public class Task010426 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();

for (int i = 0; i < 10_000; i++) {
String s = new String("data_" + i);
String interned = s.intern();
list.add(interned);
}

String a = new String("data_5000");
String b = a.intern();

System.out.println(a == b);
System.out.println(a == list.get(5000));
System.out.println(b == list.get(5000));
}
}


#Tasks
👍1
👍2
Что такое анонимные классы (Anonymous classes)? 🤓

Ответ:

Анонимные классы
— это локальные внутренние классы без имени, которые объявляются и инстанцируются одновременно в одном выражении.

Они используются, когда нужен одноразовый объект с небольшими изменениями, чаще всего для реализации интерфейсов или расширения классов (например, Runnable, компараторы, обработчики событий).

Синтаксис: new Interface() { ... } или new Class() { ... }.

Анонимные классы имеют доступ к final или effectively final переменным окружающего контекста.



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

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

Уо́лтер Пе́рси Кра́йслер (англ. Walter Percy Chrysler; 2 апреля 1875, Уомего, Канзас — 18 августа 1940, Кингс-Пойнт, Нью-Йорк) — американский автомобилестроитель, промышленник, основатель корпорации Chrysler.


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

1966 — советский спутник «Луна-10» стал первым в мире космическим аппаратом, облетевшим Луну.


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

Глава 8: За пределами коллекций. Бесконечность и I/O

Бесконечные стримы и ленивая генерация

Ранее Stream API рассматривался как инструмент обработки конечных коллекций данных. Но фундаментальная мощь потоков — в их способности моделировать бесконечные последовательности, вычисляемые по требованию. Это сдвигает фокус с "данных в памяти" к "процессу генерации", открывая паттерны для числовых последовательностей, генераторов уникальных идентификаторов, обработки потоковых источников вроде сетевых соединений.


Stream.iterate: рекурсия с состоянием

Метод Stream.iterate создаёт поток, где каждый следующий элемент вычисляется из предыдущего.

Перегрузка Java 8 принимает начальное значение и унарную функцию:
// Натуральные числа: 0, 1, 2, 3...
Stream<Integer> natural = Stream.iterate(0, n -> n + 1);

// Степени двойки: 1, 2, 4, 8...
Stream<Integer> powersOfTwo = Stream.iterate(1, n -> n * 2);

// Фибоначчи: пара (a, b) -> (b, a+b)
Stream<long[]> fibonacci = Stream.iterate(
new long[]{0, 1},
f -> new long[]{f[1], f[0] + f[1]}
);


Ключевая особенность: iterate сохраняет состояние между элементами. Это делает его непараллелизуемым — каждый элемент зависит от предыдущего, разделение невозможно. Попытка вызвать .parallel() на таком потоке не даст выигрыша, а может замедлить из-за накладных расходов.


Java 9+: iterate с предикатом остановки

Перегрузка с тремя параметрами добавляет условие продолжения:
// Числа от 0 до 99
Stream<Integer> limited = Stream.iterate(
0, // seed
n -> n < 100, // hasNext (предикат продолжения)
n -> n + 1 // next (функция следующего)
);


Это заменяет паттерн iterate(...).limit(n) более семантически ясным конструктом. Предикат проверяется перед генерацией каждого элемента, включая seed. Если hasNext(seed) ложно, поток пуст.


Stream.generate: чистая генерация без состояния

Stream.generate принимает Supplier — функцию без аргументов, возвращающую значение. Каждый вызов независим, что теоретически позволяет параллелизм (хотя реализация в OpenJDK не делит такие потоки эффективно).
// Постоянное значение
Stream<String> constants = Stream.generate(() -> "repeat");

// Случайные числа
Stream<Double> randoms = Stream.generate(Math::random);

// Уникальные ID через атомарный счётчик
AtomicLong idGenerator = new AtomicLong(0);
Stream<String> uniqueIds = Stream.generate(() -> "ID-" + idGenerator.incrementAndGet());


generate идеален для стохастических или внешне определяемых последовательностей, где нет рекуррентной зависимости. Но бесконечность требует ограничения: limit, takeWhile или короткое замыкание терминальной операцией.


takeWhile и dropWhile: предикатные границы

Java 9 добавила методы takeWhile и dropWhile, критически отличные от filter по семантике:
filter проверяет каждый элемент независимо, пропуская или отбрасывая по условию
takeWhile пропускает элементы, пока предикат истинен, и останавливает поток при первом ложном
dropWhile отбрасывает элементы, пока предикат истинен, и продолжает с первого ложного

// Сортированный поток температур
IntStream temperatures = IntStream.of(15, 18, 22, 25, 19, 12, 8);

// takeWhile: температура ниже 25
temperatures.takeWhile(t -> t < 25)
.forEach(System.out::println); // 15, 18, 22 — остановка на 25

// dropWhile: пропускаем прохладную погоду
temperatures.dropWhile(t -> t < 20)
.forEach(System.out::println); // 22, 25, 19, 12, 8


Ключевое отличие takeWhile от filter — short-circuit поведение. filter(t -> t < 25) обработал бы все элементы, включая 19, 12, 8. takeWhile останавливается, предполагая, что последовательность упорядочена и дальнейшие элементы не интересны.

Это критично для бесконечных потоков:
// Бесконечная последовательность, ограниченная условием
Stream.iterate(1, n -> n * 2)
.takeWhile(n -> n < 1000) // 1, 2, 4, 8, ..., 512 — остановка
.forEach(System.out::println);


Без takeWhile пришлось бы использовать limit, требующий знания количества элементов заранее, или filter, не останавливающийся.


#Java #для_новичков #beginner #stream_api
👍6
Сценарий: генерация уникальных идентификаторов

Комбинация generate с takeWhile или limit создаёт контролируемые генераторы:

// UUID с проверкой уникальности в пределах сессии
Set<String> usedIds = ConcurrentHashMap.newKeySet();
Stream<String> uniqueIds = Stream.generate(UUID::randomUUID)
.map(UUID::toString)
.filter(usedIds::add) // add возвращает false если уже есть, фильтруем дубликаты
.limit(1000); // строго 1000 уникальных

// Или с takeWhile для условной остановки
Stream<String> idsUntilPattern = Stream.generate(this::generateId)
.takeWhile(id -> !id.contains("STOP")); // Генерация до спецпаттерна


Атомарные структуры (AtomicLong, ConcurrentHashMap) обеспечивают потокобезопасность при параллельном доступе, хотя generate в стандартной реализации не эффективно параллелится.


Сценарий: чтение потоковых данных

Бесконечные стримы моделируют внешние источники с неизвестным объёмом:
```
// Симуляция чтения из сокета: байты до терминатора
Stream<Byte> socketStream = Stream.generate(() -> readFromSocket())
.takeWhile(b -> b != -1); // -1 как EOF

// Обработка пакетов до специального маркера
Stream<Packet> packetStream = Stream.generate(this::readNextPacket)
.takeWhile(p -> !p.isTerminator());

Важно: такие потоки требуют управления ресурсами. Stream.generate не знает о необходимости закрыть сокет. Использование в try-with-resources или явное закрытие источника в Supplier — ответственность разработчика.


Практика: числовые последовательности с ленивостью

Сравним подходы к генерации последовательностей:
// Плохо: немедленное создание списка
List<Integer> eager = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
if (isPrime(i)) eager.add(i);
}

// Хорошо: ленивый поток, элементы вычисляются по требованию
IntStream primes = IntStream.iterate(2, n -> n + 1)
.filter(this::isPrime)
.takeWhile(n -> n < 1000000);

// Потребление только первых 10, остальные никогда не вычислены
primes.limit(10).forEach(System.out::println);


Ленивость позволяет работать с "потенциально бесконечными" последовательностями, фактически обрабатывая только необходимый минимум.


Ограничения бесконечных потоков

Параллелизм: iterate не параллелится, generate — плохо. Бесконечные потоки — последовательная абстракция.
Состояние: iterate требует небольшого состояния (предыдущий элемент), но не масштабируется. Сложное состояние в Supplier требует синхронизации.
Ресурсы: бесконечность — концептуальная. Реальные источники (сокеты, файлы) требуют закрытия. Stream API не управляет жизненным циклом внешних ресурсов автоматически.


#Java #для_новичков #beginner #stream_api
👍5
Не знаю как вы, а я рад 🤪😄
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣10
Что выведет код?

import java.util.stream.Stream;

public class Task020426 {
public static void main(String[] args) {
Stream<Integer> stream = Stream.iterate(0, n -> n + 1)
.filter(n -> n % 2 == 0)
.map(n -> {
System.out.print(n + " ");
return n;
})
.limit(3);

stream.forEach(n -> {});
}
}


#Tasks
👍1
👍1
Вот можете изучить условия галер))
Что такое Method Reference (ссылки на методы)? 🤓

Ответ:

Method Reference
— это еще более краткая форма записи лямбда-выражения, когда вы просто вызываете существующий метод.

Синтаксис: ClassName::methodName.

Есть четыре типа:
ссылка на статический метод (Math::max),
ссылка на метод экземпляра конкретного объекта (System.out::println),
ссылка на метод экземпляра произвольного объекта конкретного типа (String::length),
ссылка на конструктор (ArrayList::new). Method Reference делают код еще более читаемым и лаконичным.



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

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

Не нашел((


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

1885 — немецкий изобретатель Готлиб Даймлер получил патент на свой первый двигатель — в половину лошадиной силы.

1973 – Мартин Купер из компании Motorola совершает первый звонок с мобильного телефона, используя портативное устройство, Джоэлу С. Энгелю из Bell Labs.

1981 – На выставке West Coast Computer Faire в Сан-Франциско был представлен Osborne 1, первый успешный портативный компьютер.

2010 – компания Apple Inc. выпустила первое поколение iPad , планшетного компьютера.


#Biography #Birth_Date #Events #03апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
[Совет по Java #022]

Тема: BigDecimal с конструктором от double теряет точность.

Проблема: Конструктор BigDecimal(double) принимает значение double с плавающей точкой, которое уже содержит погрешность из-за двоичного представления десятичных дробей.

Эта погрешность не исчезает при создании BigDecimal — она фиксируется и становится частью его масштаба.
Например, new BigDecimal(0.1) создает объект, равный 0.1000000000000000055511151231257827021181583404541015625, а не 0.1. Это приводит к неожиданным ошибкам при сравнении, сложении и других операциях, полностью нивелируя смысл использования BigDecimal для точных вычислений.
Ошибка коварна тем, что при выводе через System.out.println() может отобразиться округленное значение, создавая иллюзию корректности.

Решение: Используйте один из двух безопасных способов создания BigDecimal:

- BigDecimal.valueOf(double) — статический фабричный метод, который использует Double.toString() для преобразования и гарантирует точное представление десятичного значения.

- Конструктор BigDecimal(String) — самый надежный, но требует явного преобразования числа в строку.

- Никогда не используйте конструктор BigDecimal(double) для значений, которые не являются целыми или не могут быть точно представлены в двоичной системе.

import java.math.BigDecimal;

public class BigDecimalPrecision {

public static void main(String[] args) {
//Антипаттерн: конструктор от double
BigDecimal fromDouble = new BigDecimal(0.1);
System.out.println("new BigDecimal(0.1): " + fromDouble);
// Вывод: 0.1000000000000000055511151231257827021181583404541015625

//Ошибка в сравнении
BigDecimal expected = new BigDecimal("0.1");
System.out.println("Равны? " + fromDouble.equals(expected)); // false!

//Ошибка в арифметике
BigDecimal sum = new BigDecimal(0.1).add(new BigDecimal(0.2));
System.out.println("0.1 + 0.2 = " + sum);
// Вывод: 0.3000000000000000166533453693773481063544750213623046875

//Решение 1: BigDecimal.valueOf(double)
BigDecimal fromValueOf = BigDecimal.valueOf(0.1);
System.out.println("BigDecimal.valueOf(0.1): " + fromValueOf); // 0.1

//Решение 2: конструктор от String
BigDecimal fromString = new BigDecimal("0.1");
System.out.println("new BigDecimal(\"0.1\"): " + fromString); // 0.1

// Проверка равенства
System.out.println("valueOf == string: " + fromValueOf.equals(fromString)); // true

//Безопасная арифметика
BigDecimal safeSum = BigDecimal.valueOf(0.1).add(BigDecimal.valueOf(0.2));
System.out.println("Безопасная сумма: " + safeSum); // 0.3

// Для целых чисел конструктор от double безопасен
BigDecimal intValue = new BigDecimal(10.0);
System.out.println("Целое число: " + intValue); // 10
}
}


Объяснение: Ключевое различие между конструктором и фабричным методом в том, что BigDecimal.valueOf(double) сначала преобразует double в строку с помощью Double.toString(), которая использует алгоритм для получения минимального количества знаков, точно представляющих значение. Это устраняет избыточную погрешность.

Конструктор BigDecimal(String) является самым прозрачным — он парсит десятичную строку напрямую, что идеально для значений, поступающих из пользовательского ввода или API. Для целых чисел (например, 10.0) погрешность отсутствует, но безопаснее использовать BigDecimal.valueOf(10) или BigDecimal.TEN.

Статический анализ кода (SonarQube, SpotBugs) автоматически подсвечивает использование конструктора BigDecimal(double) как критический дефект.


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

import java.math.BigDecimal;

public class Task030426 {
public static void main(String[] args) {
BigDecimal bd1 = new BigDecimal(0.1);
BigDecimal bd2 = BigDecimal.valueOf(0.1);
BigDecimal bd3 = new BigDecimal("0.1");

System.out.println(bd1.equals(bd2));
System.out.println(bd1.equals(bd3));
System.out.println(bd2.equals(bd3));
System.out.println(bd1.compareTo(bd2));
}
}


#Tasks
👍2
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Как создать неизменяемый (immutable) класс? 🤓

Ответ:

Чтобы создать immutable класс, следуйте правилам:

1) Объявите класс как final (чтобы нельзя было наследовать).
2) Все поля сделайте private final.
3) Не предоставляйте сеттеры.
4) Инициализируйте все поля через конструктор, делая глубокие копии для изменяемых объектов (массивы, Date, List).
5) В геттерах для изменяемых полей возвращайте копии, а не оригинальные ссылки (Collections.unmodifiableList(), клонирование массива).

Пример: класс String.



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

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

Карл Вильгельм Сименс (4 апреля 1823 года — 19 ноября 1883 года)немецкий и британский инженер-механик, изобретатель и промышленник. Ему принадлежит ряд изобретений, в том числе регенеративного конденсатора для предварительного нагревания воды, употребляемой в пищу (1850 год), водомера (1851 год), пирометра (1860 год), гидравлического компрессора для уменьшения отката артиллерийских орудий (1867 год) и прочего.


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

1983 — состоялся первый полёт американского космического челнока «Челленджер».

1994 — основана компания
Netscape Communications (называвшаяся в то время «Mosaic Communications Corporation»).


#Biography #Birth_Date #Events #04апреля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
С 28.03 по 03.04
Предыдущий пост(с 21.03 по 27.03)

Воскресный мотивационный пост:
Не было мотивации, а вообще нужна?) (Признался что только один читает... Напишу ему в личку, наверно)

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

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

Глава 7: Stream API в экосистеме Java. Интеграционные паттерны
Рефакторинг legacy-кода в проекте «Библиотека»

Глава 8: За пределами коллекций. Бесконечность и I/O
Бесконечные стримы и ленивая генерация

[Совет по Java #020]
Тема: HashSet с изменяемыми объектами ломает контракт.

[Совет по Java #021]
Тема: Использование intern() в (String.intern()) для уникальных строк может забить PermGen/Metaspace и вызвать утечку памяти.

[Совет по Java #022]
Тема: BigDecimal с конструктором от double теряет точность.

Полезные статьи и видео:
Хватит винить кривые руки. Твой язык программирования энергетически тебе не подходит

Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍2
🔥5🤓1
🤣4