Что такое изменяемые (mutable) коллекции в Java?

Ответ

Изменяемые (mutable) коллекции в Java — это коллекции, содержимое которых можно модифицировать после создания (добавлять, удалять, изменять элементы). Это стандартное поведение для большинства реализаций в java.util (например, ArrayList, HashMap, HashSet).

Пример изменяемого ArrayList:

List<String> mutableList = new ArrayList<>();
mutableList.add("Java");     // Добавление
mutableList.set(0, "Python"); // Изменение
mutableList.remove(0);       // Удаление
mutableList.clear();         // Очистка всей коллекции

Противоположность — неизменяемые (immutable) коллекции:

  • Java 9+: Фабричные методы List.of(), Set.of(), Map.of() создают неизменяемые коллекции. Попытка модификации выбросит UnsupportedOperationException.
  • Collections.unmodifiableX(): Возвращают представление, которое нельзя изменить.
    List<String> immutableList = List.of("A", "B", "C");
    // immutableList.add("D"); // Выбросит UnsupportedOperationException

    Когда использовать mutable коллекции?

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

Важные аспекты при работе с mutable коллекциями:

  1. Потокобезопасность: Большинство mutable коллекций не являются потокобезопасными. Для работы в многопоточной среде требуется:
    • Использование коллекций из java.util.concurrent (ConcurrentHashMap, CopyOnWriteArrayList).
    • Внешняя синхронизация (Collections.synchronizedList()).
  2. Передача по ссылке: При передаче mutable коллекции в метод, изменения внутри этого метода отразятся на исходной коллекции, что может быть источником ошибок.
  3. Best practice: По возможности делайте коллекции неизменяемыми, особенно если они представляют конфигурацию или постоянные данные. Это упрощает рассуждение о коде и предотвращает случайные изменения.

Ответ 18+ 🔞

А, слушай, вот эта вся хуйня с коллекциями в Java — это вообще отдельный цирк с конями, блядь. Сидишь такой, думаешь: "О, список, щас накидаю туда данных, потом пофикшу". А потом выясняется, что ты, мудак, не ту коллекцию выбрал, и всё летит в тартарары.

Вот смотри, есть коллекции изменяемые, или, как умники говорят, mutable. Это как твой старый диван — хочешь, подушку выкинул, хочешь, новую впендюрил, а можешь и вовсе хуяк его нахуй в овраг. В Java это почти всё из java.util: ArrayList, HashMap, HashSet — обычные пацаны, с которыми можно всё.

Вот, смотри, как с ними работают:

List<String> mutableList = new ArrayList<>();
mutableList.add("Java");     // Запихнул
mutableList.set(0, "Python"); // Перезаписал, типа "ой, передумал"
mutableList.remove(0);       // Выкинул нахуй
mutableList.clear();         // А теперь всё вымел, чисто поле

А есть их полная противоположность — неизменяемые (immutable). Это как памятник Ленину в центре города — попробуй ему усы прилепи или хуй в руку вложи, сразу охрана набежит с криками UnsupportedOperationException, блядь.

  • В Java 9 и выше появились фабричные методы: List.of(), Set.of(), Map.of(). Создал — и сиди, любуйся. Ни хуя не тронешь.
  • Ещё есть Collections.unmodifiableX() — это как поставить стеклянный колпак на ту же коллекцию. Видно всё, а потрогать — нихуя.
List<String> immutableList = List.of("A", "B", "C");
// immutableList.add("D"); // Пытаешься добавить — получаешь ебаный кирпич в виде исключения. Всё.

Так когда же эти изменяемые коллекции нужны, спрашивается?

Да когда тебе надо что-то динамически ковырять, блядь! Например, данные из базы тянешь в цикле и пихаешь в список. Или кэш какой-нибудь хитрожопый делаешь, который надо обновлять. Для сложных алгоритмов, где структура данных постоянно пляшет — без них вообще никуда.

Но вот тут, сука, подводные камни начинаются, держись:

  1. Потокобезопасность, ёпта! Почти все эти обычные mutable коллекции — не потокобезопасные. Представь: два потока лезут в один ArrayList, как два мудака в одну дверь. Итог — пиздец, данные поехали, исключение ConcurrentModificationException тебе в еблет. Что делать?

    • Либо бери специальные коллекции из java.util.concurrentConcurrentHashMap, CopyOnWriteArrayList. Они с подвохом, но зато выдержат.
    • Либо оборачивай свою коллекцию в Collections.synchronizedList() — это как поставить бугая на вход, но он тормозит всё движение.
  2. Передача по ссылке — классика жанра для ошибок. Отдал ты свою изменяемую коллекцию в какой-нибудь метод, а там какой-то умник взял и хуяк — удалил половину элементов. А ты смотришь на свой исходный список и охуеваешь: "А где, блядь, мои данные?!" Это, сука, источник таких багов, что волосы дыбом встают.

  3. Лучшая практика, которую все просрали. Если коллекция представляет собой что-то постоянное — конфиги, справочники, дни недели — делай её неизменяемой с самого начала. List.of() и в продакшн. Так ты себя отсечёшь от кучи идиотских ошибок, когда кто-то случайно что-то затрёт. Код становится проще для понимания: посмотрел на сигнатуру — List<String> CONSTANTS — и сразу ясно, что это священная корова, которую трогать нельзя.

Короче, думай головой, что ты делаешь. Не надо везде пихать ArrayList по привычке. Иногда проще и надёжнее сделать коллекцию каменной, и спать спокойно.