Что такое иммутабельная (неизменяемая) коллекция в Java?

Ответ

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

Способы создания в современных Java (9+):

// 1. Фабричные методы of() (Java 9+)
List<String> immutableList = List.of("A", "B", "C");
Set<String> immutableSet = Set.of("A", "B");
Map<String, Integer> immutableMap = Map.of("Key1", 1, "Key2", 2);

// immutableList.add("D"); // UnsupportedOperationException
// immutableSet.remove("A"); // UnsupportedOperationException

// 2. Копирование существующей коллекции (Java 10+)
List<String> mutableList = new ArrayList<>(Arrays.asList("X", "Y", "Z"));
List<String> copiedImmutableList = List.copyOf(mutableList);

// 3. Unmodifiable-обёртка (Java 1.2+). ВАЖНО: это вид неизменяемости.
List<String> innerList = new ArrayList<>();
innerList.add("One");
List<String> unmodifiableView = Collections.unmodifiableList(innerList);
// unmodifiableView.add("Two"); // UnsupportedOperationException
innerList.add("Two"); // А это сработает! unmodifiableView теперь содержит ["One", "Two"]

Преимущества:

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

Недостатки:

  • Производительность: Создание новой коллекции при каждом изменении может быть затратным для больших или часто меняющихся данных.
  • Потребление памяти: Может привести к созданию множества объектов.

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

Ответ 18+ 🔞

Смотри, тут про коллекции, которые как будто в бетон залили — раз создал, и всё, нихуя не поменяешь. Иммутабельные, блядь. Любое действие, типа "добавь-ка мне этот элемент", не меняет старую коллекцию, а создаёт новую, свеженькую, как будто старую клонировали, но с апгрейдом.

Как их наклепать в современной Java (9 и выше):

// 1. Фабричные методы of() (Java 9+) — просто и элегантно, как удар в лоб
List<String> immutableList = List.of("A", "B", "C");
Set<String> immutableSet = Set.of("A", "B");
Map<String, Integer> immutableMap = Map.of("Key1", 1, "Key2", 2);

// immutableList.add("D"); // Вылетит UnsupportedOperationException — типа, "не-не-не, браток, не надь"
// immutableSet.remove("A"); // Та же песня, нихуя не выйдет

// 2. Сделать копию с уже готовой коллекции (Java 10+)
List<String> mutableList = new ArrayList<>(Arrays.asList("X", "Y", "Z"));
List<String> copiedImmutableList = List.copyOf(mutableList); // Всё, мутабельную убили, теперь это памятник

// 3. Unmodifiable-обёртка (ещё со времён динозавров, Java 1.2+). ВНИМАНИЕ, подстава!
List<String> innerList = new ArrayList<>();
innerList.add("One");
List<String> unmodifiableView = Collections.unmodifiableList(innerList);
// unmodifiableView.add("Two"); // Опять исключение, кажется, всё ок
innerList.add("Two"); // А вот это, сука, сработает! И наша "неизменяемая" вьюха теперь содержит ["One", "Two"]! Это не настоящая иммутабельность, это обман зрения, пиздёж!

Чем они офигенны:

  • Потокобезопасность на раз: Можно хоть сотне потоков её тыкать — данные не поменяются, синхронизация не нужна, живи спокойно.
  • Предсказуемость, как у будильника: Исключены внезапные пиздецы, когда кто-то в другом углу системы накосячил с коллекцией.
  • Безопасность передачи: Можешь хоть в космос её отправить как ключ для Map — никто не подменит, не испортит.

Чем они могут подбесить:

  • Производительность: Если ты с ними как с обычными списками работаешь — постоянно создавать новые объекты, это, блядь, овердохуища операций, особенно на больших данных.
  • Память: Можешь насоздавать кучу объектов, а они все будут висеть, как призраки прошлого.

Где их применять? Да везде, где данные должны быть высечены в камне: конфиги, какие-то постоянные справочники, или когда нужно безопасно перекинуть данные между потоками, чтобы не было "ой, а я тут мимоходом поменял". Главное — понимать, что это не просто обёртка, а именно новый, отдельный, неприкосновенный объект.