Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое иммутабельная коллекция?
Иммутабельная коллекция (Immutable Collection) — это коллекция, которая не может быть изменена после создания. После инициализации нельзя добавлять, удалять или модифицировать элементы. Это мощный инструмент для безопасности потоков и предотвращения ошибок.
Проблемы с изменяемыми коллекциями
// ❌ ПРОБЛЕМА: изменяемая коллекция
final List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
// Кто-то может изменить список в другом потоке
list.clear(); // Ops! Список очищен
list.remove(0);
list.set(0, "orange");
// В многопоточной среде это приводит к race conditions
public void processItems(List<String> items) {
for (String item : items) {
// Во время итерации кто-то может изменить items
// ConcurrentModificationException!
process(item);
}
}
Создание иммутабельных коллекций
1. Collections.unmodifiable*
import java.util.*;
public class UnmodifiableExample {
public static void main(String[] args) {
List<String> mutableList = new ArrayList<>();
mutableList.add("apple");
mutableList.add("banana");
// ✅ Создаём неизменяемую коллекцию
List<String> immutableList = Collections.unmodifiableList(mutableList);
// ❌ UnsupportedOperationException
immutableList.add("orange"); // Ошибка!
immutableList.remove(0); // Ошибка!
immutableList.set(0, "grape"); // Ошибка!
// ⚠️ Но! Если изменить исходный список, изменится и "иммутабельный"
mutableList.add("pear");
System.out.println(immutableList); // [apple, banana, pear] !
}
}
// ✅ Иммутабельные коллекции для других типов
Set<Integer> immutableSet = Collections.unmodifiableSet(new HashSet<>(nums));
Map<String, Integer> immutableMap = Collections.unmodifiableMap(new HashMap<>(data));
2. List.of(), Set.of(), Map.of() (Java 9+)
import java.util.*;
public class ModernImmutable {
public static void main(String[] args) {
// ✅ Java 9+: истинно иммутабельные коллекции
List<String> list = List.of("apple", "banana", "cherry");
Set<Integer> set = Set.of(1, 2, 3, 4, 5);
Map<String, Integer> map = Map.of(
"apple", 10,
"banana", 20,
"cherry", 30
);
// ❌ UnsupportedOperationException
list.add("orange"); // Ошибка!
set.remove(1); // Ошибка!
map.put("grape", 40); // Ошибка!
// ✅ Полностью безопасно — нет связи с исходными данными
List<String> fruits = new ArrayList<>();
fruits.add("apple");
List<String> immutable = List.copyOf(fruits);
fruits.add("banana"); // Не влияет на immutable
}
}
Иммутабельные коллекции в многопоточной среде
import java.util.concurrent.*;
import java.util.*;
public class ThreadSafetyExample {
// ❌ НЕБЕЗОПАСНО
static class UnsafeUserRepository {
private List<User> users = new ArrayList<>(); // Изменяемо!
public List<User> getUsers() {
return users; // Опасно! Кто-то может изменить
}
}
// ✅ БЕЗОПАСНО
static class SafeUserRepository {
private final List<User> users = List.of(); // Иммутабельно
public List<User> getUsers() {
return users; // Безопасно! Никто не может изменить
}
// Если нужна обновка — создаём новый список
public void addUser(User user) {
List<User> newUsers = new ArrayList<>(users);
newUsers.add(user);
// synchronized и обновляем ссылку
synchronized (this) {
this.users = List.copyOf(newUsers);
}
}
}
}
Пример с Streams
import java.util.*;
import java.util.stream.Collectors;
public class StreamImmutable {
public void processData(List<String> data) {
// ✅ Создаём иммутабельный список из stream
List<String> uppercase = data.stream()
.map(String::toUpperCase)
.collect(Collectors.toUnmodifiableList());
// ✅ Иммутабельный set
Set<String> uniqueItems = data.stream()
.collect(Collectors.toUnmodifiableSet());
// ✅ Иммутабельная map
Map<String, Integer> lengths = data.stream()
.collect(Collectors.toUnmodifiableMap(
Function.identity(),
String::length
));
}
}
Вспомогательные библиотеки
Google Guava ImmutableCollections
import com.google.common.collect.*;
public class GuavaImmutable {
public void examples() {
// ImmutableList
ImmutableList<String> list = ImmutableList.of("a", "b", "c");
ImmutableList<String> list2 = ImmutableList.<String>builder()
.add("x", "y", "z")
.add("more items")
.build();
// ImmutableSet
ImmutableSet<Integer> set = ImmutableSet.of(1, 2, 3);
// ImmutableMap
ImmutableMap<String, Integer> map = ImmutableMap.of(
"a", 1,
"b", 2
);
// Все они невозможно изменить
// list.add("d"); // UnsupportedOperationException
}
}
Apache Commons Lang
import org.apache.commons.lang3.tuple.Pair;
import java.util.Collections;
public class CommonsImmutable {
// ...existing code...
}
Иммутабельные классы
import java.util.*;
// ✅ Иммутабельный класс
public final class ImmutableUser {
private final String name;
private final int age;
private final List<String> tags; // Иммутабельная коллекция
public ImmutableUser(String name, int age, List<String> tags) {
this.name = name;
this.age = age;
// Создаём copy для защиты
this.tags = List.copyOf(tags);
}
public String getName() { return name; }
public int getAge() { return age; }
public List<String> getTags() { return tags; } // Безопасно вернуть
// Для изменения — создаём новый объект
public ImmutableUser withName(String newName) {
return new ImmutableUser(newName, this.age, this.tags);
}
}
Запись параметров (Java 16+)
// ✅ Record — автоматически иммутабельный
public record User(String name, int age, List<String> tags) {
// Компилятор автоматически создаст:
// - private final поля
// - конструктор
// - getters
// - equals/hashCode/toString
}
public void example() {
User user = new User("John", 30, List.of("developer", "java"));
// user.name = "Jane"; // Ошибка компиляции!
}
Преимущества иммутабельных коллекций
- Потокобезопасность — не нужны блокировки
- Простота — меньше ошибок логики
- Кэширование — можно кэшировать без опасений
- Производительность — JVM может оптимизировать
- Предсказуемость — значения не изменяются неожиданно
Недостатки
- Производительность — copy-on-write медленнее для частых изменений
- Памяти — может требовать больше памяти
- Гибкость — нельзя просто изменить, нужно создавать новый объект
Лучшие практики
// ✅ Возвращай иммутабельные коллекции из методов
public List<User> getUsers() {
return Collections.unmodifiableList(users);
// или
return List.copyOf(users);
}
// ✅ Создавай иммутабельные коллекции для constans
private static final List<String> VALID_STATUSES = List.of("ACTIVE", "INACTIVE", "DELETED");
// ✅ Используй иммутабельные классы для value objects
public final class Money {
private final BigDecimal amount;
private final Currency currency;
// ...
}
Иммутабельные коллекции — критически важны в современной Java разработке, особенно в многопоточных приложениях!