Копирование списка в Java: Метод Collections.copy() и его применение
Быстрый ответ
Для создания поверхностной копии списка можно использовать конструктор new ArrayList<>(originalList)
. Если целевой список уже готов принять элементы, подойдет метод Collections.copy(dest, src)
. Для осуществления глубокого копирования изменяемых объектов рекомендуется комбинация map-stream-collect.
List<String> src = Arrays.asList("apple", "banana", "cherry");
List<String> shallow = new ArrayList<>(src);
List<String> dest = new ArrayList<>(Collections.nCopies(src.size(), null));
Collections.copy(dest, src);
List<MyObject> deep = src.stream()
.map(MyObject::new)
.collect(Collectors.toList());
Подготовка контейнеров для копирования
Копирование коллекций – сложный процесс, не сводящийся к простому перемещению объектов. Все зависит от формата копии – поверхностной или глубокой, а также от типа объектов в списке. Поверхностное копирование передает ссылки и подходит для неизменяемых объектов, например, строк. Для изменяемых объектов применимо глубокое копирование. А метод Collections.copy()
удобен для вставки уже существующих элементов в список заданного размера.
Размер важен для списков-получателей
Не забывайте проверять, что размер списка-получателя равен размеру копируемого списка перед использованием Collections.copy()
:
Collections.copy(new ArrayList<>(originalList.size()), originalList);
Невыполнение этого условия приведет к ошибке IndexOutOfBoundsException
. Поэтому стоит заранее заботиться о размере списка-получателя.
Изменяемые объекты и их клонирование
Глубокая копия – это решение для списков с изменяемыми объектами. Если в вашем распоряжении пользовательские объекты, которые можно клонировать, сделайте следующее:
List<MyObject> deep = originalList.stream()
.map(myObj -> myObj.clone())
.collect(Collectors.toList());
Копирование с помощью Guava и метода Lists.newArrayList
Для продвинутого копирования подойдет метод Lists.newArrayList()
из библиотеки Guava:
List<String> guavaCopy = Lists.newArrayList(originalList);
Обновление элементов с помощью метода List.set
Если нужно вставить элементы по индексам, используйте List.set(int, E)
:
for (int i = 0; i < originalList.size(); i++) {
copyList.set(i, new MyObject(originalList.get(i)));
}
Визуализация
Введем представление процесса копирования списка в Java Collections:
List<String> originalList = new ArrayList<>(Arrays.asList("Java", "Python", "C++"));
List<String> copyList = new ArrayList<>(originalList);
Представьте, будто происходит космическая операция:
📄 Оригинальный список: [🔍 "Java", 🐍 "Python", 💻 "C++"]
🖨️ Клонирующая машина: начинаем клонирование...
📄 Копия списка: [🔍 "Java", 🐍 "Python", 💻 "C++"]
Каждый элемент из оригинального списка получает точную копию в списке-клоне.
Производительность и зарание выделенный объем
Не всегда имеет смысл создавать списки с большим заранее заданным объемом – это не гарантия ускорения работы. Необходимо избегать "золотого баланса", основанного на мифах.
Глубокое копирование и класс объекта
Методы глубокого копирования зависят от класса объектов, универсального решения нет.
Collections.copy
и эффективное использование сборщика мусора
С Collections.copy()
можно эффективно работать с большими списками, минимизируя нагрузку на сборщик мусора.
Полезные материалы
- Collection (Java Platform SE 8) – Детальная информация о Java Collections Framework.
- java.util.Collections.copy() Method – Все, что вам нужно знать о методе Collections.copy().
- java – How to clone ArrayList and also clone its contents? – Stack Overflow – Обсуждение вопроса клонирования списков и их содержимого в сообществе.
- Collections – Home – Обзор дополнительных функций из Apache Common Collections.
- GitHub – kostaskougios/cloning: deep clone java objects – Библиотека для глубокого клонирования объектов в Java с примерами кода.