Каков наилучший способ создания нового списка из старого, но с объектами из этого списка, которые не имеют одинаковой ссылки [duplicate]

Вы можете сделать это более просто, используя plot() вместо plot_date().

Сначала преобразуем ваши строки в экземпляры Python datetime.date:

import datetime as dt

dates = ['01/02/1991','01/03/1991','01/04/1991']
x = [dt.datetime.strptime(d,'%m/%d/%Y').date() for d in dates]
y = range(len(x)) # many thanks to Kyss Tao for setting me straight here

Затем сюжет:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator())
plt.plot(x,y)
plt.gcf().autofmt_xdate()

Результат:

enter image description here [/g0]

230
задан Lii 24 August 2016 в 16:01
поделиться

16 ответов

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

Edit: ... и это именно то, что делает код Вархана.

170
ответ дан Lii 15 August 2018 в 20:46
поделиться
  • 1
    Однако вы не можете делать это в общем. clone () не является частью интерфейса Cloneable. – Michael Myers♦ 3 April 2009 в 21:47
  • 2
    И даже если они это сделают, нет никакого способа получить доступ к clone (), кроме отражения, и это не гарантирует успеха в любом случае. – Michael Myers♦ 3 April 2009 в 21:48
  • 3
    Но clone () защищен в Object, поэтому вы не можете получить к нему доступ. Попробуйте скомпилировать этот код. – Michael Myers♦ 3 April 2009 в 21:49
  • 4
    Все классы расширяют Object, поэтому они могут переопределять clone (). Это то, к чему клонируется! – Stephan202 3 April 2009 в 21:50
  • 5
    Это хороший ответ. Cloneable - фактически интерфейс. Тем не менее, mmyers имеет точку, в которой метод clone () является защищенным методом, объявленным в классе Object. Вам придется переопределить этот метод в вашем классе Dog и вручную выполнить ручное копирование полей. – Jose Chavez 3 April 2009 в 21:50
  • 6
    Ответ Вархана неверен. – erickson 3 April 2009 в 21:50
  • 7
    Давайте продолжим обсуждение под знаком Вархана :) – Stephan202 3 April 2009 в 21:50
  • 8
    Я имею в виду цитирование ответа Вархана этим ответом. – erickson 3 April 2009 в 21:53
  • 9
    Я говорю: создайте фабрику или строитель или даже статический метод, который возьмет экземпляр Dog и вручную скопирует поля в новый экземпляр и вернет этот новый экземпляр. – Jose Chavez 3 April 2009 в 21:55
  • 10
    @erickson: Я отправил свой комментарий параллельно с вашим. В любом случае, ответ обновляется. – Stephan202 3 April 2009 в 22:04
  • 11
    не нужно, чтобы все эти 3 варианта создавали мелкие копии списков – electrobabe 15 March 2016 в 14:57
  • 12
    Видите ли вы какое-либо влияние на производительность этого способа, когда Dog (d) является конструктором копирования? List<Dog> clonedDogs = new ArrayList<>(); dogs.stream().parallel().forEach(d -> clonedDogs.add(new Dog(d))); – SaurabhJinturkar 28 July 2016 в 23:55
  • 13
    @SaurabhJinturkar: Ваша версия не является потокобезопасной и не должна использоваться с параллельными потоками. Это связано с тем, что вызов parallel вызывает вызов clonedDogs.add из нескольких потоков одновременно. Версии, использующие collect, являются потокобезопасными. Это одно из преимуществ функциональной модели библиотеки потоков, тот же код может использоваться для параллельных потоков. – Lii 29 July 2016 в 15:36
  • 14
    @SaurabhJinturkar: Кроме того, операция сбора выполняется быстро. Это почти то же самое, что и ваша версия, но также работает для параллельных потоков. Вы можете исправить свою версию, используя, например, параллельную очередь вместо списка массивов, но я почти уверен, что это будет намного медленнее. – Lii 29 July 2016 в 15:39
  • 15
    Всякий раз, когда я пытаюсь использовать ваше решение, я получаю Unhandled exception type CloneNotSupportedException на d.clone(). Объявить исключение или поймать его не решит. – Gustavo 23 August 2016 в 14:25
  • 16
    @Gustavo: Это почти наверняка, потому что объект, который вы клонируете, (Dog в этом примере) не поддерживает клонирование. Вы уверены, что он реализует интерфейс Clonable? – Lii 23 August 2016 в 15:06
  • 17
    Это не глубокий клон, эти два списка сохраняют одни и те же объекты, просто скопировали только ссылки, но объекты «Собаки», как только вы изменили один из них, следующий список будет иметь такое же изменение. donno y так много upvotes. – Neeson.Z 12 October 2016 в 01:55
  • 18
    @ Neeson.Z Все методы создают глубокую копию списка и мелкие копии элемента списка. Если вы измените элемент списка, изменение будет отражено другим списком, но если вы измените один из списка (например, удалив объект), другой список не изменится. – Alessandro Teruzzi 7 June 2018 в 15:08
170
ответ дан Lii 5 September 2018 в 20:10
поделиться
172
ответ дан Lii 29 October 2018 в 03:54
поделиться

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

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

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

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

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

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

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

18
ответ дан alexdriedger 15 August 2018 в 20:46
поделиться
  • 1
    Одно из предостережений с этим методом заключается в том, что он использует отражение, которое может быть довольно медленным, чем решение Вархана. – cdmckay 21 June 2010 в 07:24
  • 2
    Я не понимаю первую точку и требует много кода. В библиотеке, о которой вы говорите, потребуется больше кода. Это только вопрос о том, где вы его размещаете. В противном случае я согласен, что специальная библиотека для такого рода вещей помогает. – nawfal 7 August 2013 в 11:41
  • 3
    Ссылка Google Code теперь перенаправляется на github.com/kostaskougios/cloning – Stuart Marks 7 February 2017 в 17:19

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

public static <T> List<T> copyList(List<T> source) {
    List<T> dest = new ArrayList<T>();
    for (T item : source) { dest.add(item); }
    return dest;
}
0
ответ дан Andrew Coyte 15 August 2018 в 20:46
поделиться

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

ArrayList<Dog> clonedList = new ArrayList<Dog>(name_of_arraylist_that_you_need_to_Clone);
0
ответ дан besartm 15 August 2018 в 20:46
поделиться

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

class Dog
{
    public Dog()
    { ... } // Regular constructor

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

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

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

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

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

169
ответ дан cdmckay 15 August 2018 в 20:46
поделиться
  • 1
    +1 Конструктор копирования - это путь. Также нравится идея интерфейса ICloneable. – helpermethod 15 March 2010 в 22:46
  • 2
    Хорошее и простое решение, мне это нравится! – Micer 21 April 2013 в 21:17
  • 3
    можете ли вы более конкретно скопировать все поля DOG. Я действительно не понимаю :( – Dr. aNdRO 23 April 2014 в 16:05
  • 4
    Можно ли написать эту функцию для неопределенного объекта (вместо Dog)? – Tobi G. 15 February 2016 в 00:01
  • 5
    @TobiG. Я не понимаю, что вы имеете в виду. Вы хотите cloneList(List<Object>) или Dog(Object)? – cdmckay 15 February 2016 в 02:17

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

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

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

Из Эффективное Java 2nd Edition , пункт 11: разумно отвергнуть клон

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

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

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

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

121
ответ дан Community 15 August 2018 в 20:46
поделиться
  • 1
    Насколько мне известно, конструкторы копирования стандартных коллекций создают копию мелкой , а не копию deep . Заданный здесь вопрос дает глубокий ответ. – Abdull 29 November 2012 в 19:30
  • 2
    это просто неправильно, конструкторы копирования делают мелкую копию - весь вопрос – NimChimpsky 13 February 2013 в 17:41
  • 3
    Правильность этого ответа в том, что если вы не мутируете объекты в списке, добавление или удаление элементов не удаляет их из обоих списков. Это не как нечеткое как простое назначение. – Noumenon 15 August 2015 в 20:55

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

ArrayList<String>arrayB = new ArrayList<String>();
arrayB.addAll(arrayA);

Сообщите мне, если это не сработает для вас.

-1
ответ дан demongolem 15 August 2018 в 20:46
поделиться
  • 1
    не работает, если вы используете List & lt; List & lt; JsonObject & gt; & gt; & gt; например, в моем случае – djdance 14 August 2017 в 11:06
  • 2
    Строки неизменяемы. Клонирование не имеет смысла, и в вашем примере массив и массив имеют одинаковые ссылки на объекты - его мелкую копию. – Christian Fries 3 August 2018 в 14:57

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

0
ответ дан Eduardo de Melo 15 August 2018 в 20:46
поделиться

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

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

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

0
ответ дан Fortyrunner 15 August 2018 в 20:46
поделиться

Отвратительный способ - сделать это с отражением. Что-то вроде этого сработало для меня.

public static <T extends Cloneable> List<T> deepCloneList(List<T> original) {
    if (original == null || original.size() < 1) {
        return new ArrayList<>();
    }

    try {
        int originalSize = original.size();
        Method cloneMethod = original.get(0).getClass().getDeclaredMethod("clone");
        List<T> 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<>();
    }
}
1
ответ дан milosmns 15 August 2018 в 20:46
поделиться
  • 1
    Аккуратный и неприятный трюк! Одна потенциальная проблема: если original содержит объекты разных классов, я думаю, что cloneMethod.invoke потерпит неудачу с исключением, когда он вызывается с неправильным видом объекта. Из-за этого было бы лучше получить конкретный клон Method для каждого объекта. Или используйте метод clone на Object (но поскольку он защищен, что может быть неудачным в большем числе случаев). – Lii 24 August 2016 в 07:44
  • 2
    Кроме того, я думаю, было бы лучше выбросить исключение во время выполнения в catch-clause вместо того, чтобы возвращать пустой список. – Lii 24 August 2016 в 07:46

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

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

Пример

this.myObjectCloned = SerializationUtils.clone(this.object);
0
ответ дан nhahtdh 15 August 2018 в 20:46
поделиться
  • 1
    это немного устарело, чтобы ответить на этот вопрос. И многие другие ответы в комментарии по этому вопросу. – moskito-x 2 May 2013 в 20:49

для вас объекты переопределяют метод 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 ....

0
ответ дан RN3KK Nick 15 August 2018 в 20:46
поделиться

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

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

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

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

-1
ответ дан sagits 15 August 2018 в 20:46
поделиться
  • 1
    Я не знаю, почему люди отказались от этого ответа. Другие ответы должны реализовать clone () или изменить их зависимости для включения новых библиотек. Но библиотека JSon, большая часть проектов уже была включена. Я поддержал это. – Satish 22 March 2018 в 19:13

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

link download commons-lang-2.3.jar

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

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

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

: D

0
ответ дан sonida 15 August 2018 в 20:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: