Как я могу клонировать, ArrayList
а также клонировать его элементы в Java?
Например у меня есть:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
И я ожидаю, что объекты clonedList
не такие, как в списке собак.
java
collections
clone
deep-copy
palig
источник
источник
Ответы:
Вам нужно будет перебирать элементы и клонировать их один за другим, помещая клоны в массив результатов по мере продвижения.
Очевидно, что для того, чтобы это работало, вам нужно будет заставить ваш
Dog
класс реализоватьCloneable
интерфейс и переопределитьclone()
метод.источник
Лично я бы добавил конструктор в Dog:
Затем просто повторяем (как показано в ответе Вархана):
Я нахожу преимущество в том, что вам не нужно разбираться со сломанным Cloneable в Java. Это также соответствует тому, как вы копируете коллекции Java.
Другой вариант - написать свой собственный интерфейс ICloneable и использовать его. Таким образом, вы можете написать общий метод для клонирования.
источник
cloneList(List<Object>)
илиDog(Object)
?Все стандартные коллекции имеют конструкторы копирования. Используй их.
clone()
был разработан с несколькими ошибками (см. этот вопрос ), поэтому лучше избегать этого.Из Эффективной Java, 2-е издание , пункт 11: разумно переопределить клон
Эта книга также описывает множество преимуществ конструкторов копирования по сравнению с Cloneable / clone.
Рассмотрим еще одно преимущество использования конструкторов копирования. Предположим, у вас есть
HashSet s
и вы хотите скопировать его какTreeSet
. Метод клон не может предложить такую функциональность, но это легко с помощью конструктора преобразования:new TreeSet(s)
.источник
Java 8 предоставляет новый способ элегантного и компактного вызова конструктора копирования или метода клонирования на элементах Dogs: потоки , лямбды и коллекторы .
Скопируйте конструктор:
Выражение
Dog::new
называется ссылкой на метод . Он создает объект функции, который вызывает конструктор,Dog
который принимает в качестве аргумента другую собаку.Метод клонирования [1]:
Получение
ArrayList
в результатеИли, если вам нужно получить
ArrayList
обратно (если вы хотите изменить его позже):Обновите список на месте
Если вам не нужно сохранять исходное содержимое
dogs
списка, вы можете вместо этого использоватьreplaceAll
метод и обновить список на месте:Все примеры предполагаем
import static java.util.stream.Collectors.*;
.Коллектор для
ArrayList
сСборщик из последнего примера может быть превращен в метод util. Поскольку это настолько распространенная вещь, мне лично нравится, чтобы она была короткой и красивой. Как это:
[1] Примечание к
CloneNotSupportedException
:Чтобы это решение работало,
clone
методDog
не должен объявлять, что он выбрасываетCloneNotSupportedException
. Причина в том, что аргумент tomap
не может генерировать какие-либо проверенные исключения.Как это:
Это не должно быть большой проблемой, так как в любом случае это лучшая практика. ( Effectice Java, например, дает этот совет.)
Спасибо Густаво за то, что заметил это.
PS:
Если вы найдете это красивее, вы можете использовать синтаксис ссылки на метод, чтобы сделать то же самое:
источник
List<Dog> clonedDogs = new ArrayList<>(); dogs.stream().parallel().forEach(d -> clonedDogs.add(new Dog(d)));
parallel
вызов делаетclonedDogs.add
вызов из нескольких потоков одновременно. Версии, которые используют,collect
являются потокобезопасными. Это одно из преимуществ функциональной модели потоковой библиотеки, один и тот же код можно использовать для параллельных потоков.Unhandled exception type CloneNotSupportedException
наd.clone()
. Объявление исключения или его отлов не решают проблему.Dog
в этом примере) не поддерживает клонирование. Вы уверены, что он реализуетClonable
интерфейс?В основном есть три способа без итерации вручную,
1 Использование конструктора
2 Использование
addAll(Collection<? extends E> c)
3 Использование
addAll(int index, Collection<? extends E> c)
метода сint
параметромNB. Поведение этих операций будет неопределенным, если указанная коллекция будет изменена во время выполнения операции.
источник
Я думаю, что текущий зеленый ответ плохой , почему вы можете спросить?
Сериализация также плоха, но вам, возможно, придется добавить Serializable повсеместно.
Итак, каково решение:
Библиотека глубокого клонирования Java Библиотека клонирования - это небольшая библиотека Java с открытым исходным кодом (лицензия Apache), которая глубоко клонирует объекты. Объекты не должны реализовывать интерфейс Cloneable. По сути, эта библиотека может клонировать ЛЮБЫЕ объекты Java. Его можно использовать, например, в реализациях кэша, если вы не хотите, чтобы кэшированный объект был изменен или когда вы хотите создать глубокую копию объектов.
Проверьте это на https://github.com/kostaskougios/cloning
источник
Я нашел способ, вы можете использовать json для сериализации / десериализации списка. Сериализованный список не содержит ссылки на исходный объект, если он не сериализован.
Используя gson:
Вы можете сделать это, используя Джексона и любую другую библиотеку JSON тоже.
источник
Я использовал эту опцию всегда:
источник
Вам нужно будет клонировать
ArrayList
объект вручную (перебрав его и скопировав каждый элемент в новыйArrayList
), потому чтоclone()
он не сделает это за вас. Причиной этого является то, что объекты, содержащиеся в,ArrayList
могут не реализовыватьClonable
сами.Изменить : ... и это именно то, что делает код Varkhan.
источник
Гадкий способ сделать это с помощью отражения. Нечто подобное сработало для меня.
источник
original
содержит объекты разных классов, я думаю, чтоcloneMethod.invoke
произойдет сбой с исключением, когда он вызывается с неправильным видом объекта. Из-за этого может быть лучше получить определенный клонMethod
для каждого объекта. Или используйте метод клонированияObject
(но поскольку этот метод защищен, в некоторых случаях он может потерпеть неудачу).Это будет глубоко копировать каждую собаку
источник
Остальные постеры верны: вам нужно перебрать список и скопировать в новый список.
Однако ... Если объекты в списке неизменны - вам не нужно их клонировать. Если у вашего объекта есть сложный граф объектов - они также должны быть неизменными.
Другое преимущество неизменности заключается в том, что они также безопасны для потоков.
источник
Вот решение с использованием универсального типа шаблона:
источник
для вас объекты переопределяют метод clone ()
и вызовите .clone () для Vector obj или ArraiList obj ....
источник
Простой способ с помощью commons-lang-2.3.jar этой библиотеки Java для клонирования списка
ссылка для скачивания commons-lang-2.3.jar
Как пользоваться
Я надеюсь, что это может быть полезным.
: D
источник
Посылка
import org.apache.commons.lang.SerializationUtils;
Есть метод
SerializationUtils.clone(Object);
пример
источник
Я только что разработал библиотеку, которая может клонировать объект сущности и объект java.util.List. Просто скачайте флягу в https://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0U и используйте статический метод cloneListObject (список списка). Этот метод не только клонирует список, но и все элементы сущности.
источник
Ниже работал для меня ..
в Dog.java
Здесь новый список, созданный методом createCopy, создается через SerializationUtils.clone (). Таким образом, любое изменение, внесенное в новый список, не повлияет на исходный список.
источник
Я думаю, что нашел действительно простой способ сделать глубокую копию ArrayList. Предполагая, что вы хотите скопировать массив ArringList StringA.
Дайте мне знать, если это не сработает для вас.
источник