Java for Beginner
869 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
Вопрос с собеседований

Что такое backpressure? 🤓

Ответ:

Backpressure
— механизм, позволяющий потребителю регулировать скорость производителя данных.

Без него быстрый источник перегружает систему.

Реализуется в Reactive Streams через запросы определённого количества элементов.


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


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

Ма́ртин Ку́пер (англ. Martin Cooper, род. 26 декабря 1928, Чикаго) — американский инженер и физик, известен как человек, совершивший первый звонок по сотовому телефону.

3 апреля 1973 года Купер совершил первый публичный звонок с портативного мобильного телефона, работая в компании Motorola, с тротуара Манхэттена своему коллеге из конкурирующей компании Bell Labs . В 1973 году Купер создал первый портативный сотовый мобильный телефон (отличный от автомобильного телефона) и возглавил команду, которая переработала его и вывела на рынок в 1983 году. Он считается «отцом (портативного) сотового телефона», и получил премию IEEE Masaru Ibuka Consumer Electronics Award 2015 года за эту работу.


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

1898 – Мария и Пьер Кюри объявляют об выделении радия.


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

Глава 8. Дополнительные аспекты коллекций


Неизменяемые коллекции: List.of, Set.of, Collections.unmodifiableList

Неизменяемость (immutability) представляет собой одну из фундаментальных парадигм современного программирования, уходящую корнями в функциональное программирование и математику. В контексте коллекций неизменяемость означает, что после создания коллекция не может быть модифицирована — ни добавлением, ни удалением, ни изменением существующих элементов. Эта концепция противостоит традиционному императивному подходу, где мутация состояния является нормой, и предлагает альтернативный путь к созданию более надежных, предсказуемых и безопасных систем.


Историческая эволюция неизменяемых коллекций в Java

До Java 9 разработчики вынуждены были использовать обходные пути для создания неизменяемых коллекций. Основным инструментом был класс Collections с его методами unmodifiableXXX, которые создавали обертки над изменяемыми коллекциями. Однако эти обертки имели существенные ограничения и могли быть обойдены при неправильном использовании.

С выходом Java 9 была представлена революционная концепция фабричных методов для создания истинно неизменяемых коллекций: List.of(), Set.of(), Map.of(). Эти методы не просто создавали обертки, а возвращали специализированные реализации, которые с самого начала проектировались как неизменяемые.



Фундаментальные принципы неизменяемых коллекций

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

Это смещение парадигмы приводит к нескольким важным следствиям:
Упрощение рассуждений о коде: Не нужно отслеживать последовательность мутаций
Повышение надежности: Исключены побочные эффекты от неожиданных изменений
Улучшение тестируемости: Состояние фиксировано и предсказуемо


Принцип безвредности (No Side Effects)

Неизменяемые коллекции строго следуют принципу отсутствия побочных эффектов. Операции над ними не изменяют исходные данные, а создают новые коллекции. Этот принцип заимствован из функционального программирования и математики, где функции не имеют побочных эффектов.


Фабричные методы в Java 9+: List.of(), Set.of(), Map.of()

Введение фабричных методов в Java 9 стало результатом многолетнего развития языка и осознания важности неизменяемости. Эти методы представляют собой не просто синтаксический сахар, а фундаментальное изменение в дизайне API коллекций.


List.of(): Создание неизменяемых списков


List.of() предоставляет 12 перегруженных версий для разного количества элементов:
// Различные сигнатуры
List.of() // Пустой список
List.of(e1) // Один элемент
List.of(e1, e2) // Два элемента
// ... до 10 элементов
List.of(e1, e2, ..., e10) // Десять элементов
List.of(elements...) // Varargs для любого количества


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

За фасадом List.of() скрываются специализированные реализации:
Пустой список: Возвращается синглтон ImmutableCollections.EMPTY_LIST
Список из 1-2 элементов: Используются компактные классы ImmutableCollections.List1, List2
Списки более 2 элементов: Используется общая реализация ImmutableCollections.ListN
Каждая из этих реализаций оптимизирована для своего сценария использования, что обеспечивает минимальный overhead по памяти и максимальную производительность.


Особенности семантики

Запрет null элементов: Все методы List.of() выбрасывают NullPointerException при попытке добавить null
Структурная неизменяемость: Не поддерживаются операции добавления, удаления, замены
Итераторы: Возвращаются итераторы, не поддерживающие операцию remove()
Сериализация: Специальная поддержка для эффективной сериализации


#Java #для_новичков #beginner #immutability #Collection #List_of #Set_of
👍4
Set.of(): Неизменяемые множества

В отличие от списков, множества предъявляют дополнительное требование — уникальность элементов.


Методы Set.of() строго проверяют это требование:
Set.of("a", "b", "c");        // Допустимо
Set.of("a", "b", "a"); // IllegalArgumentException: дубликат


Внутренняя структура


Для множеств также существуют оптимизированные реализации:
Пустое множество: Синглтон ImmutableCollections.EMPTY_SET
Множество из 1 элемента: ImmutableCollections.Set1
Множество из 2 элементов: Используется специальная структура для двух элементов
Большие множества: Используется ImmutableCollections.SetN на основе хэш-таблицы


Особенности производительности

Малые множества (до 2 элементов) используют особые алгоритмы сравнения, что делает операции contains() чрезвычайно эффективными — O(1) с очень малой константой.


Map.of(): Неизменяемые отображения

Для создания неизменяемых отображений используются два подхода:
// Прямое создание пар (до 10 пар)
Map.of(k1, v1, k2, v2, ..., k10, v10)

// Создание из пар Map.Entry
Map.ofEntries(
Map.entry(k1, v1),
Map.entry(k2, v2),
// ...
)


Требования к ключам

Как и для множеств, ключи в Map.of() должны быть уникальными. Попытка создания отображения с дублирующимися ключами приводит к IllegalArgumentException.

Внутренняя оптимизация

Для малых отображений используются специализированные реализации:
Пустое отображение: ImmutableCollections.EMPTY_MAP
Отображение из 1 пары: ImmutableCollections.Map1
Отображение из 2 пар: Используется оптимизированная структура
Для больших отображений используется массив пар ключ-значение с линейным поиском, что для небольших N (до ~10) оказывается эффективнее хэш-таблиц.



Collections.unmodifiableXXX(): Подход до Java 9

Методы Collections.unmodifiableList(), unmodifiableSet(), unmodifiableMap() и другие создают обертки над существующими изменяемыми коллекциями. Эти обертки делегируют операции чтения исходной коллекции, но запрещают операции модификации.

Механизм работы

Архитектура обертки
// Концептуальная реализация unmodifiableList
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof UnmodifiableList) ?
(List<T>) list :
new UnmodifiableList<>(list);
}

static class UnmodifiableList<E> implements List<E> {
private final List<E> list;

UnmodifiableList(List<E> list) {
this.list = list;
}

public E get(int index) {
return list.get(index); // Делегирование
}

public void add(int index, E element) {
throw new UnsupportedOperationException(); // Запрет модификации
}
// ... остальные методы
}


Уровни неизменяемости


Важно понимать, что unmodifiableXXX создают только поверхностную (shallow) неизменяемость:
Структурная неизменяемость: Размер и состав коллекции не могут быть изменены
Элементная изменяемость: Объекты внутри коллекции могут быть изменяемыми


List<StringBuilder> list = new ArrayList<>();
list.add(new StringBuilder("Hello"));
List<StringBuilder> unmodifiable = Collections.unmodifiableList(list);

// Нельзя изменить структуру
unmodifiable.add(new StringBuilder("World")); // UnsupportedOperationException

// Но можно изменить содержимое элементов
unmodifiable.get(0).append(" World"); // Допустимо!


Исторический контекст


До Java 9 подход с unmodifiableXXX был единственным стандартным способом создания неизменяемых представлений.

Однако у него было несколько существенных недостатков:
Изменяемость исходной коллекции: Обертка отражает изменения в исходной коллекции
Возможность обхода защиты: Через приведение типов или reflection
Производительность: Дополнительный уровень индирекции



#Java #для_новичков #beginner #immutability #Collection #List_of #Set_of
👍5
Сравнительный анализ подходов

Null-безопасность

Методы List.of() и аналогичные полностью запрещают null элементы, что способствует написанию более безопасного кода. В противоположность этому, unmodifiableXXX позволяют null, если их разрешает исходная коллекция.

Поведение при модификации

// Пример с List.of()
List<String> immutable = List.of("A", "B", "C");
// Любая попытка модификации: UnsupportedOperationException

// Пример с unmodifiableList
List<String> mutable = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> wrapper = Collections.unmodifiableList(mutable);

mutable.add("D"); // Изменяем исходный список
System.out.println(wrapper); // ["A", "B", "C", "D"] - обертка отражает изменения
Это фундаментальное различие: List.of() создает полностью независимую коллекцию, тогда как unmodifiableList() создает зависимое представление.


Производительность в деталях

Для List.of() с малым количеством элементов доступ по индексу может быть реализован через прямое поле:
// Концептуально для List.of(e1, e2)
class List2<E> extends AbstractImmutableList<E> {
private final E e0, e1;

public E get(int index) {
return switch (index) {
case 0 -> e0;
case 1 -> e1;
default -> throw new IndexOutOfBoundsException();
};
}
}


В то время как unmodifiableList всегда требует двойной диспетчеризации: вызов метода обертки → делегирование исходной коллекции.

Итерация

Итераторы для List.of() не имеют логики проверки модификаций и не поддерживают remove(), что делает их более легковесными.


Принципы проектирования неизменяемых коллекций

Паттерн "Builder" для сложных случаев

Для создания сложных неизменяемых коллекций Java предоставляет строители (builders):
// Для List
List<String> list = List.<String>builder()
.add("A")
.addAll(anotherList)
.build();

// Для Map
Map<String, Integer> map = Map.<String, Integer>builder()
.put("key1", 1)
.put("key2", 2)
.build();

Эти строители позволяют создавать неизменяемые коллекции инкрементально, что особенно полезно при динамическом построении.


Копирование с преобразованием

Частый паттерн — создание неизменяемой коллекции на основе существующей с фильтрацией или преобразованием:
List<String> mutable = Arrays.asList("A", "B", "C", null, "D");

// Фильтрация null и создание неизменяемого списка
List<String> immutable = mutable.stream()
.filter(Objects::nonNull)
.map(String::toUpperCase)
.collect(Collectors.toUnmodifiableList());



Безопасность в многопоточных сценариях

Потокобезопасность по умолчанию

Неизменяемые коллекции от природы потокобезопасны. Поскольку их состояние не может быть изменено после создания, множество потоков может одновременно читать коллекцию без какой-либо синхронизации.

Memory visibility


Благодаря принципам Java Memory Model, правильно опубликованная неизменяемая коллекция гарантирует, что все потоки увидят корректное состояние ее элементов:
// Безопасная публикация
public class Configuration {
public static final List<String> SETTINGS = List.of("A", "B", "C");
// Все потоки увидят полностью инициализированную коллекцию
}


Отсутствие race conditions

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

Сравнение с synchronized коллекциями
// Synchronized подход (устаревший)
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
// Требует внешней синхронизации для compound операций

// CopyOnWriteArrayList (частичная неизменяемость)
CopyOnWriteArrayList<String> copyOnWrite = new CopyOnWriteArrayList<>();
// Дорогие операции записи, но безопасное чтение

// Полностью неизменяемый подход
List<String> immutable = List.of("A", "B", "C");
// Идеальная потокобезопасность без накладных расходов



#Java #для_новичков #beginner #immutability #Collection #List_of #Set_of
👍5
Практические паттерны использования

Конфигурации и константы
public class ApplicationConstants {
// Конфигурационные параметры
public static final List<String> SUPPORTED_LANGUAGES =
List.of("en", "es", "fr", "de");

public static final Map<String, Integer> DEFAULT_SETTINGS =
Map.of("timeout", 30, "retries", 3, "cacheSize", 1000);
}


Возврат из методов

public List<String> getActiveUsers() {
// Вместо возврата изменяемого списка
return List.copyOf(internalUserList); // Защитная копия как неизменяемый список
}


Параметры методов
public void processItems(List<String> items) {
// items должен быть неизменяемым или защищенной копией
List<String> safeItems = List.copyOf(items);
// Далее работаем с safeItems
}



Ограничения и когда не использовать

Динамические коллекции

Неизменяемые коллекции не подходят для сценариев, где требуется частое изменение состава:
// НЕПРАВИЛЬНО: постоянное создание новых коллекций
List<String> items = List.of();
for (Item item : source) {
items = Stream.concat(items.stream(), Stream.of(item.getName()))
.collect(Collectors.toUnmodifiableList()); // Очень дорого!
}

// ПРАВИЛЬНО: использование изменяемого построителя
List<String> itemsBuilder = new ArrayList<>();
for (Item item : source) {
itemsBuilder.add(item.getName());
}
List<String> items = List.copyOf(itemsBuilder);


Большие коллекции

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


Best practices

1. Предпочитайте List.of() над Arrays.asList()
// Хорошо
List<String> good = List.of("A", "B", "C");

// Плохо (возвращает изменяемый список, но фиксированного размера)
List<String> bad = Arrays.asList("A", "B", "C");


2. Защитное копирование при необходимости
public class SafeApi {
private final List<String> data;

public SafeApi(List<String> input) {
// Защитное копирование в неизменяемый список
this.data = List.copyOf(input);
}
}


3. Документируйте неизменяемость
/**
* Возвращает неизменяемый список активных пользователей.
* Попытки модификации приведут к UnsupportedOperationException.
*/
public List<User> getActiveUsers() {
return Collections.unmodifiableList(internalList);
}


4. Используйте соответствующие типы в сигнатурах
// Хорошо: ясно указывает на намерение
public void processItems(List<? extends String> items) {
// items может быть любым списком строк, включая неизменяемые
}

// Или даже лучше в Java 16+
public void processItems(SequencedCollection<String> items) {
// Явное указание на коллекцию с определенным порядком
}



Отладка и диагностика

Выявление скрытых модификаций

Для отладки проблем с неожиданными модификациями можно использовать обертки с логированием:
public static <T> List<T> loggingUnmodifiableList(List<T> list) {
return new AbstractList<T>() {
@Override
public T get(int index) {
return list.get(index);
}

@Override
public int size() {
return list.size();
}

@Override
public void add(int index, T element) {
logError("Attempt to modify unmodifiable list at index " + index);
throw new UnsupportedOperationException();
}
};
}


Профилирование использования памяти

Неизменяемые коллекции могут привести к неожиданному потреблению памяти, если создается много временных коллекций.

Профилирование помогает выявить такие проблемы:
// Мониторинг создания коллекций
public class CollectionMonitor {
private static final AtomicLong listCreations = new AtomicLong();

public static <E> List<E> monitoredListOf(E... elements) {
listCreations.incrementAndGet();
return List.of(elements);
}

public static long getCreationCount() {
return listCreations.get();
}
}



#Java #для_новичков #beginner #immutability #Collection #List_of #Set_of
👍4
Что выведет код?

import java.util.*;

public class Task261225 {
public static void main(String[] args) {
Integer[] array = {1, 2, 3};
List<Integer> list1 = Arrays.asList(array);
List<Integer> list2 = List.of(array);
List<Integer> list3 = Collections.unmodifiableList(list1);

array[1] = 20;

System.out.println(list2.get(1));
System.out.println(list3.get(1));
}
}


#Tasks
👍3
Варианты ответа:
Anonymous Quiz
0%
20 20
25%
2 20
25%
20 2
50%
2 2
👍1😱1
Вопрос с собеседований

Как именно JVM определяет, что объект доступен для GC? 🤓

Ответ:

JVM использует алгоритмы достижимости (reachability analysis).

Объект считается живым, если до него можно добраться от GC Roots: локальных переменных стека, статических полей, активных потоков, JNI-ссылок.

Если путь отсутствует — объект помечается как мусор.


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


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

Не нашел((


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

2004 – Излучение от взрыва магнетара SGR 1806-20 достигает Земли. Это самое яркое из известных внесолнечных явлений, наблюдавшихся на планете.


#Biography #Birth_Date #Events #27Декабря
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Предлагаю завтра встретиться в 16:00 по МСК и наконец-то понять, что такое Tree и как оно используется в Java! 🤓

Информацию готовит @ElizaFanat, за что ему огромное спасибо!

С собой берите предновогоднее настроение 🎄 и неподдельный интерес. На входе будет досмотр 😉😄

Жду всех!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
История IT-технологий сегодня — 28 декабря


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

Ли́нус Бенедикт То́рвальдс (встречается написание Ту́рвальдс) (швед. Linus Benedict Torvalds МФА: [ˈliːn.ɵs ˈtuːr.valds]о файле; род. 28 декабря 1969, Хельсинки) — финно-американский программист. Воодушевлённый прочтением книги Эндрю Таненбаума, посвящённой операционной системе Minix, Линус создал Linux — ядро операционной системы GNU/Linux, являющейся на данный момент самой распространённой из свободных операционных систем, а также наиболее популярной серверной ОС.

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

1895 – Вильгельм Рентген публикует статью, в которой подробно описывает свое открытие нового типа излучения , которое впоследствии станет известно как рентгеновские лучи.


#Biography #Birth_Date #Events #28Декабря
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Всем привет! ✌️

Напоминаю, что сегодня в 16:00 бот выдаст Вам ссылку на встречу, где вы точно узнаете что такое Tree в Java.

Приходите будет интересно. 🤫
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Я б поржать сходил 😂


https://t.me/Java_for_beginner_dev

#Mems
🔥3
Интересно это про какой фраймворк? 🤔


https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
🤓1🆒1
У всех сеньоров порой так бывает? 🤓


https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
🤓2
👾3
Встреча создана!

Бот @JFB_admin_bot выдаст ссылку. Для корректной работы лучше его перезапустить)

Залетаем ✈️
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Tree в Java.
Самая сложная коллекция.

В представленном видео, мы подробно разобрали, что такое Tree и как они представлены в Java.

Огромное спасибо @ElizaFanat за рассказ и демонстрации. 🙂

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

Смотрите, ставьте лайки, подписывайтесь на каналы!
✌️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2