Как клонировать ArrayList, а также клонировать его содержимое?

Как я могу клонировать ArrayList а также клонировать его элементы в Java?

Например, у меня есть:

 ArrayList dogs = getDogs(); ArrayList clonedList = ....something to do with dogs.... 

И я ожидал бы, что объекты в clonedList не совпадают, как в списке собак.

Вам нужно будет перебирать элементы и клонировать их один за другим, помещая клоны в массив результатов, когда вы идете.

 public static List cloneList(List list) { List clone = new ArrayList(list.size()); for (Dog item : list) clone.add(item.clone()); return clone; } 

Для этого, очевидно, вам придется получить объект Dog для реализации интерфейса Cloneable и метода clone ().

Я лично добавлю конструктора в Dog:

 class Dog { public Dog() { ... } // Regular constructor public Dog(Dog dog) { // Copy all the fields of Dog. } } 

Затем просто повторите (как показано в ответе Вархана):

 public static List cloneList(List dogList) { List clonedList = new ArrayList(dogList.size()); for (Dog dog : dogList) { clonedList.add(new Dog(dog)); } return clonedList; } 

Я нахожу преимущество этого – вам не нужно вкручиваться со сломанным клонированным материалом на Java. Он также соответствует тому, как вы копируете коллекции Java.

Другой вариант – написать собственный интерфейс ICloneable и использовать его. Таким образом, вы можете написать общий метод клонирования.

Все стандартные коллекции имеют конструкторы копирования. Используй их.

 List original = // some list List copy = new ArrayList(original); //This does a shallow copy 

clone() был разработан с несколькими ошибками (см. этот вопрос ), поэтому лучше избегать его.

Из Effective Java 2nd Edition , пункт 11: разумно переопределить клон

Учитывая все проблемы, связанные с Cloneable, можно с уверенностью сказать, что другие интерфейсы не должны расширять его, а classы, предназначенные для наследования (пункт 17), не должны реализовывать его. Из-за многих недостатков некоторые экспертные программисты просто не рекомендуют переопределять метод клонирования и никогда не вызывать его, кроме, возможно, для копирования массивов. Если вы создаете class для наследования, имейте в виду, что если вы решите не предоставлять хорошо защищенный метод клонирования, для подclassов невозможно реализовать Cloneable.

В этой книге также описываются многие преимущества, которые создатели копий имеют над Cloneable / clone.

  • Они не полагаются на механизм создания экстралингвистического объекта, подверженного риску
  • Они не требуют необоснованного соблюдения тонко документированных конвенций
  • Они не противоречат правильному использованию конечных полей
  • Они не выбрасывают ненужные проверенные исключения
  • Они не требуют отбрасываний.

Рассмотрим еще одно преимущество использования конструкторов копирования: предположим, что у вас есть HashSet s , и вы хотите скопировать его как TreeSet . Метод clone не может предлагать эту функциональность, но с конструктором преобразования легко: new TreeSet(s) .

Java 8 предоставляет новый способ вызова конструктора копирования или метода clone на элементарных элементах элегантно и компактно: streamи , лямбды и коллекторы .

Конструктор копирования:

 List clonedDogs = dogs.stream().map(Dog::new).collect(toList()); 

Выражение Dog::new называется ссылкой на метод . Он ссылается на конструктор на Dog который берет другую собаку в качестве аргумента.

Метод клонирования:

 List clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList()); 

Получение ArrayList в результате

Или, если вам нужно вернуть ArrayList (если вы хотите изменить его позже):

 ArrayList clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new)); 

Обновите список на месте

Если вам не нужно сохранять исходное содержимое списка dogs вы можете использовать метод replaceAll и обновить список вместо этого:

 dogs.replaceAll(Dog::new); 

Все примеры предполагают import static java.util.stream.Collectors.*; ,


Коллекционер для ArrayList

Коллектор из последнего примера может быть превращен в метод утилизации. Поскольку это такая распространенная вещь, мне лично нравится, чтобы она была короткой и красивой. Как это:

 ArrayList clonedDogs = dogs.stream().map(d -> d.clone()).collect(toArrayList()); public static  Collector> toArrayList() { return Collectors.toCollection(ArrayList::new); } 

Примечание по CloneNotSupportedException :

Для этого решения для работы метод clone Dog не должен объявлять, что он вызывает CloneNotSupportedException . Причина в том, что аргумент для map не допускается к выбросу каких-либо проверенных исключений.

Как это:

  // Note: Method is public and returns Dog, not Object @Override public Dog clone() /* Note: No throws clause here */ { ... 

Однако это не должно быть большой проблемой, так как это лучшая практика. ( Например, Effectice Java дает этот совет.)

Спасибо Густаво за это.


PS:

Если вы найдете его более красивым, вы можете вместо этого использовать синтаксис ссылок метода, чтобы сделать то же самое:

 List clonedDogs = dogs.stream().map(Dog::clone).collect(toList()); 

В принципе существует три способа без итерации вручную,

1 Использование конструктора

 ArrayList dogs = getDogs(); ArrayList clonedList = new ArrayList(dogs); 

2 Использование addAll(Collection c)

 ArrayList dogs = getDogs(); ArrayList clonedList = new ArrayList(); clonedList.addAll(dogs); 

3 Использование addAll(int index, Collection c) метод с параметром int

 ArrayList dogs = getDogs(); ArrayList clonedList = new ArrayList(); clonedList.addAll(0, dogs); 

NB: поведение этих операций будет неопределенным, если указанная коллекция будет изменена во время выполнения операции.

Я думаю, что текущий зеленый ответ плох , почему вы можете спросить?

  • Может потребоваться добавить много кода
  • Он требует, чтобы вы перечислили все списки, которые нужно скопировать, и сделайте это

Способ сериализации также плохой imo, возможно, вам придется добавить Serializable по всему месту.

Итак, каково решение:

Библиотека Java Deep-Cloning Библиотека клонирования – это небольшая библиотека Java с открытым исходным кодом (apache license), которая глубоко клонирует объекты. Объектам не нужно реализовывать интерфейс Cloneable. Эффективно, эта библиотека может клонировать ЛЮБЫЕ java-объекты. Его можно использовать, то есть в реализациях кеша, если вы не хотите, чтобы кешированный объект был изменен или когда вы хотите создать глубокую копию объектов.

 Cloner cloner=new Cloner(); XX clone = cloner.deepClone(someObjectOfTypeXX); 

Проверьте это на странице https://github.com/kostaskougios/cloning

Вам нужно будет клонировать ArrayList вручную (путем итерации по нему и копирования каждого элемента в новый ArrayList ), потому что clone() не сделает это за вас. Причина этого в том, что объекты, содержащиеся в ArrayList могут не реализовывать Clonable .

Изменить : … и это именно то, что делает код Вархана.

Жалкий способ сделать это с reflectionм. Что-то вроде этого сработало для меня.

 public static  List deepCloneList(List original) { if (original == null || original.size() < 1) { return new ArrayList<>(); } try { int originalSize = original.size(); Method cloneMethod = original.get(0).getClass().getDeclaredMethod("clone"); List clonedList = new ArrayList<>(); // noinspection ForLoopReplaceableByForEach for (int i = 0; i < originalSize; i++) { // noinspection unchecked clonedList.add((T) cloneMethod.invoke(original.get(i))); } return clonedList; } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { System.err.println("Couldn't clone list due to " + e.getMessage()); return new ArrayList<>(); } } 

Другие плакаты верны: вам нужно перебирать список и копировать в новый список.

Однако … Если объекты в списке неизменяемы – вам не нужно клонировать их. Если ваш объект имеет сложный граф объектов, они также должны быть неизменными.

Другим преимуществом неизменности является то, что они также являются streamобезопасными.

Вот решение, использующее общий тип шаблона:

 public static  List copyList(List source) { List dest = new ArrayList(); for (T item : source) { dest.add(item); } return dest; } 

для вас объекты переопределяют метод clone ()

 class You_class { int a; @Override public You_class clone() { You_class you_class = new You_class(); you_class.a = this.a; return you_class; } } 

и вызовите .clone () для объекта Vector obj или ArraiList obj ….

Простой способ, используя commons-lang-2.3.jar, что библиотека java для клонирования списка

link загрузить commons-lang-2.3.jar

Как использовать

 oldList......... List newList = new ArrayList(); foreach(YourObject obj : oldList){ newList.add((YourObject)SerializationUtils.clone(obj)); } 

Надеюсь, это поможет.

: D

import org.apache.commons.lang.SerializationUtils; пакета import org.apache.commons.lang.SerializationUtils;

Существует метод SerializationUtils.clone(Object);

пример

 this.myObjectCloned = SerializationUtils.clone(this.object); 

Я только что разработал lib, способный клонировать объект entity и объект java.util.List. Просто загрузите банку в https://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0U и используйте статический метод cloneListObject (Список списков). Этот метод не только клонирует список, но также и все элементы сущности.

Я всегда использовал эту опцию:

 ArrayList clonedList = new ArrayList(name_of_arraylist_that_you_need_to_Clone); 

Я нашел способ, вы можете использовать json для сериализации / unserialize списка. Сериализованный список не ссылается на исходный объект при несериализации.

Использование gson:

 List originalList = new ArrayList<>(); // add some items later String listAsJson = gson.toJson(originalList); List newList = new Gson().fromJson(listAsJson, new TypeToken>() {}.getType()); 

Вы можете сделать это с помощью джексона и любой другой библиотеки json.

Я думаю, что нашел очень простой способ сделать глубокую копию ArrayList. Предполагая, что вы хотите скопировать массив ArrayList String.

 ArrayListarrayB = new ArrayList(); arrayB.addAll(arrayA); 

Дайте мне знать, если это не сработает для вас.

  • Фильтрация коллекций в C #
  • Как наиболее элегантно перебирать параллельные коллекции?
  • Уведомлять ObservableCollection при изменении позиции
  • Использование размера коллекции для сравнения циклов
  • Lambda выражение для преобразования массива / Список строк в массив / Список целых чисел
  • Почему нет ConcurrentHashSet против ConcurrentHashMap
  • Правильное удаление целого из списка
  • Почему в Java нет SortedList?
  • Различия между HashMap и Hashtable?
  • Публикация / подписка на несколько подмножеств одной и той же серверной коллекции
  • Вывод Big-O для реализации Java Collections Framework?
  • Interesting Posts

    Есть ли способ ограничить maxdepth для ls -Rhal?

    Как занести в черный список конкретную зону памяти в Windows?

    Как разрешить устаревший плагин (например, Adobe Flash Player) в Opera 30.0.1835.88 (и ранее)?

    Применение формата% number к значению ячейки с использованием OpenXML

    Как интерпретировать блокировку против неблокирующих присвоений в Verilog?

    В чем разница между видимостью: скрытой и отображаемой: нет?

    iphone – NSTimers в фоновом режиме

    Может ли провайдер по-прежнему видеть, какие URL-адреса посещают при использовании VPN?

    Как перечислить файлы в JAR-файле?

    Объявление пользовательского элемента пользовательского интерфейса Android с использованием XML

    Переносите мой раздел восстановления ноутбуков, сохраняя его загрузочным

    как добавить даты в java простой формат даты

    Создание новой структуры подкаталогов в ClearCase?

    Получить текущее время в C

    mvn release: подготовить не совершать изменений в pom.xml

    Давайте будем гением компьютера.