Как получить неизменяемый список из ArrayList?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Получение неизменяемого списка из ArrayList
Основные способы
1. Collections.unmodifiableList() — классический подход
Это наиболее распространённый способ, работает со всеми версиями Java:
ArrayList<String> mutableList = new ArrayList<>();
mutableList.add("Apple");
mutableList.add("Banana");
// Получаем неизменяемый лист
List<String> immutableList = Collections.unmodifiableList(mutableList);
// Попытка модификации вызовет UnsupportedOperationException
immutableList.add("Cherry"); // ❌ Исключение!
Важный нюанс: это не глубокая копия. Если изменить исходный ArrayList, изменения будут видны в неизменяемом списке:
ArrayList<String> mutableList = new ArrayList<>();
mutableList.add("Apple");
List<String> immutableList = Collections.unmodifiableList(mutableList);
mutableList.add("Banana");
// immutableList теперь содержит ["Apple", "Banana"]
System.out.println(immutableList); // [Apple, Banana]
Если нужна настоящая неизменяемость с защитой от внешних изменений, создайте копию:
List<String> trueImmutable = Collections.unmodifiableList(
new ArrayList<>(mutableList)
);
2. List.copyOf() — современный подход (Java 10+)
Это рекомендуемый способ для современного кода:
ArrayList<String> mutableList = new ArrayList<>();
mutableList.add("Apple");
mutableList.add("Banana");
// Создаёт неизменяемую копию
List<String> immutableList = List.copyOf(mutableList);
// Попытка модификации вызовет UnsupportedOperationException
immutableList.add("Cherry"); // ❌ Исключение!
// Изменения в исходном списке НЕ повлияют на копию
mutableList.add("Orange");
System.out.println(immutableList); // [Apple, Banana]
Преимущества List.copyOf():
- Создаёт настоящую копию
- Гарантирует полную неизменяемость
- Оптимизирован для производительности
- Если передана null ссылка, выбросит NullPointerException
3. Stream API (Java 8+)
ArrayList<String> mutableList = new ArrayList<>();
mutableList.add("Apple");
mutableList.add("Banana");
List<String> immutableList = mutableList.stream()
.collect(Collectors.toUnmodifiableList());
// Или с jdk.incubator (Java 10+)
List<String> immutableList2 = mutableList.stream()
.collect(Collectors.toList()); // Создаёт неизменяемый список
4. List.of() — для инициализации (Java 9+)
Если нужно сразу создать неизменяемый список:
// Не из ArrayList, но альтернатива
List<String> immutableList = List.of(
"Apple", "Banana", "Cherry"
);
immutableList.add("Orange"); // ❌ UnsupportedOperationException
Сравнение подходов
| Способ | Java | Копирует | Защита | Рекомендация |
|---|---|---|---|---|
| Collections.unmodifiableList() | 1.2+ | Нет | Частичная | Старый код |
| List.copyOf() | 10+ | Да | Полная | ✅ Лучший выбор |
| Stream.toUnmodifiableList() | 10+ | Да | Полная | Для потоков |
| List.of() | 9+ | Да | Полная | Для инициализации |
Производительность
// Контрольный пример
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 1_000_000; i++) {
list.add(i);
}
long start = System.nanoTime();
List<Integer> unmodifiable = Collections.unmodifiableList(list);
long time1 = System.nanoTime() - start; // ~100 ns (просто обёртка)
start = System.nanoTime();
List<Integer> copyOf = List.copyOf(list);
long time2 = System.nanoTime() - start; // ~10 ms (копирует данные)
Collections.unmodifiableList() быстрее, но List.copyOf() безопаснее.
Рекомендации
- Используйте List.copyOf() — если нужна настоящая неизменяемость и Java 10+
- Используйте Collections.unmodifiableList() — для старого кода, но помните о ссылках
- Передавайте неизменяемые списки в методы параметром, чтобы гарантировать целостность данных
- Избегайте null в неизменяемых списках (List.copyOf() не допускает null элементов)
Соврменный стандартный подход — List.copyOf() для его надёжности и простоты.