Каков наилучший способ клонировать карту в java? [Дубликат]

Если у вас работает Jupyter / Ipython ноутбук и проблемы с ним:

ax = df1.plot()

df2.plot(ax=ax)

Выполнить команду внутри того же клетка !! По какой-то причине это не работает, когда они разделяются на последовательные ячейки. По крайней мере для меня.

65
задан Cœur 19 August 2017 в 17:00
поделиться

8 ответов

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

  • Он добавляет много кода
  • Он требует, чтобы вы перечислили все поля, которые нужно скопировать и делать это
  • Это не будет работать для списков при использовании clone () (Это то, что clone () для HashMap говорит: возвращает неглубокую копию этого экземпляра HashMap: ключи и ценности не клонируются.) так что вы в конечном итоге делаете это вручную (это заставляет меня плакать)

О, и, кстати, сериализация также плоха, вам, возможно, придется добавить Serializable повсюду (это также заставляет меня плакать ).

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

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

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

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

51
ответ дан Tanmay Patil 15 August 2018 в 21:02
поделиться
  • 1
    Cloner - отличная библиотека (только ее исполнение иногда заставляет меня плакать ... но я думаю, вы не можете сделать гораздо лучше с отражением) – mik01aj 8 November 2010 в 09:28
  • 2
    Это решение выглядит лучше. Не пытайтесь, но есть пара комментариев в этой теме, которые очень положительно относятся к клонированию. – Juraj 15 February 2011 в 13:54
  • 3
    Не работает на Android ... – wieczorek1990 25 May 2013 в 23:12
  • 4
    Каким был предыдущий зеленый ответ? – DaveFar 25 August 2013 в 23:54
  • 5

Все подходы к копированию объектов в Java имеют серьезные недостатки:

Clone

  1. Метод clone () защищен, поэтому вы не можете вызвать его напрямую, если только класс пересматривает его с помощью общедоступного метода.
  2. clone () не вызывает конструктор. Любой конструктор. Он будет выделять память, назначить внутреннее поле class (которое вы можете прочитать через getClass()) и скопировать поля оригинала.

Для получения дополнительных сведений о проблемах с clone () см. пункт 11 книги Джошуа Блоха « Эффективная Java, второе издание »

Сериализация

Сериализация еще хуже; он имеет много недостатков clone(), а затем некоторых. Мое решение

Мое решение добавляет новый интерфейс к моим проектам:

public interface Copyable<T> {
    T copy ();
    T createForCopy ();
    void copyTo (T dest);
}

Мое решение добавляет новый интерфейс к моим проектам:

public interface Copyable<T> {
    T copy ();
    T createForCopy ();
    void copyTo (T dest);
}

Код выглядит так:

class Demo implements Copyable<Demo> {
    public Demo copy () {
        Demo copy = createForCopy ();
        copyTo (copy);
        return copy;
    }
    public Demo createForCopy () {
        return new Demo ();
    }
    public void copyTo (Demo dest)
        super.copyTo (dest);
        ...copy fields of Demo here...
    }
}

К сожалению, мне нужно скопировать этот код ко всем моим объектам, но это всегда один и тот же код, поэтому я могу использовать шаблон редактора Eclipse. Преимущества:

  1. Я могу решить, какой конструктор вызвать и как инициализировать это поле.
  2. Инициализация происходит в детерминированном порядке (класс root для класса экземпляра)
  3. Я могу повторно использовать существующие объекты и перезаписать их
  4. Тип safe
  5. Синглоты остаются синглонами

Для стандартных типов Java (например, коллекции и т. д.) ), Я использую класс утилиты, который может их скопировать. Методы имеют флаги и обратные вызовы, поэтому я могу контролировать, насколько глубока копия.

18
ответ дан Aaron Digulla 15 August 2018 в 21:02
поделиться
  • 1
    Я сделал что-то подобное, выполнив clone () во всех классах, которые мне нужно клонировать. Самая большая проблема в том, что если у меня есть коллекция, я должен перебирать ее и копировать ее сам ... – Juraj 20 March 2009 в 15:36
  • 2
    Используйте вспомогательную функцию, которая принимает коллекцию и возвращает ArrayList: поскольку вы знаете размер, который будет выделять память только один раз, и ArrayList быстро подходит для обычных видов доступа. – Aaron Digulla 20 March 2009 в 15:45
  • 3
    createForCopy необходимо вернуть демоверсию – TimP 6 July 2015 в 13:22
  • 4
    Не могли бы вы рассмотреть шаблон редактора Eclipse? – Michal 30 March 2016 в 08:42

Неглубокое клонирование коллекции легко, но если вы хотите использовать глубокий клон, библиотека, вероятно, сделает вас лучше, чем ручное кодирование (так как вы хотите клонировать элементы внутри в коллекции) .

Так же, как этот ответ , я использовал библиотеку Cloner и, в частности, протестировал его против XStream (который может «клонировать» путем сериализации десериализация) и двоичной сериализации. Хотя XStream очень быстро выполняет сериализацию в / из xml, Cloner намного быстрее при клонировании:

0.0851 ms: xstream (клонирование путем сериализации / десериализации) 0.0223 ms: двоичная сериализация (клонирование путем сериализации / десериализации) 0.0017 ms: cloner * среднее время клонирования простого объекта (два поля) и стандартного конструктора public. Выполняйте 10 000 раз.

В дополнение к быстрому, здесь больше причин выбирать клонирование:

  1. выполняет глубокий клон любого объекта (даже те, которые вы не записывайте себя)
  2. вам не нужно постоянно обновлять метод clone () каждый раз, когда вы добавляете поле
  3. , вы можете клонировать объекты, t имеет стандартный конструктор по умолчанию
  4. работает с Spring
  5. (оптимизация) не клонирует известные неизменяемые объекты (например, Integer, String и т. д.)
  6. easy использовать. Пример: cloner.deepClone (anyObject);
15
ответ дан Community 15 August 2018 в 21:02
поделиться

Одна из возможностей заключается в использовании сериализации:

Apache Commons предоставляет SerializationUtils

10
ответ дан CorayThan 15 August 2018 в 21:02
поделиться
  • 1
    Решение сериализации - это хорошо, но я думал о чем-то без него. Я могу гарантировать, что мой пользовательский объект будет правильно глубоко клонирован с помощью метода clone (), но мне нужен помощник, который сделает это для стандартных классов Java. – Juraj 20 March 2009 в 13:28
  • 2
    Сериализация способ клонировать в порядке, но у меня были некоторые поля, которые не под моим контролем и которые не являются сериализуемыми ... – Juraj 23 March 2009 в 13:32

Используйте сериализацию, а затем десериализацию, но имейте в виду, что этот подход работает только с классами Serializable без переходных полей. Кроме того, ваши синглтоны больше не будут одиночными.

0
ответ дан Eric Leschinski 15 August 2018 в 21:02
поделиться
  • 1
    Использование сериализации и десериализации для работы клонирования объектов памяти во время выполнения или между отдельными прогонами программы - плохая идея. Для получения дополнительной информации о том, почему это так, google: & quot; почему сериализация и десериализация плохо ". – Eric Leschinski 6 May 2015 в 20:24

Я создатель клонирования lib, тот, который представил Брэд. Это решение для клонирования объектов без необходимости писать дополнительный код (нет необходимости в сериализуемых объектах или методе impl clone ())

Это довольно быстро, как сказал Брэд, и недавно я загрузил версию, которая даже Быстрее. Обратите внимание, что ручное внедрение метода clone () будет быстрее, чем clone lib, но опять же вам нужно будет написать много кода.

Cloner lib работал для меня хорошо, так как я его использую в реализации кэша для сайта с очень интенсивным трафиком (~ 1 млн запросов / день). Кэш должен клонировать приблизительно 10 объектов на запрос. Он достаточно надежный и стабильный. Но, пожалуйста, имейте в виду, что клонирование не без риска. Lib может быть настроен для печати каждого экземпляра класса, который он клонирует во время dev. Таким образом, вы можете проверить, клонирует ли он то, что, по вашему мнению, нужно клонировать, - графы объектов могут быть очень глубокими и содержать ссылки на удивительно большое количество объектов. С помощью clone lib вы можете поручить ему не клонировать объекты, которые вам не нужны, т. Е. Синглтоны.

12
ответ дан Konstantinos Kougios 15 August 2018 в 21:02
поделиться
  • 1
    Библиотека выглядит отлично, проверит ее спустя некоторое время ... – Juraj 2 November 2009 в 15:55
  • 2
    «С помощью clone lib вы можете поручить ему не клонировать объекты, которые вам не нужны». Я пытался это сделать, но не мог, как я могу попросить его не клонировать определенные поля? – Sudarshan 21 July 2012 в 15:46
  • 3
    Приветствую Константинос. Я использую вашу библиотеку вместо Apache utils (у вас были проблемы с переводами с помощью SerializableUtils). Твой работает без проблем. Отличная работа!. – will824 12 March 2015 в 22:33
  • 4
    Я использую ur lib в течение длительного времени, это действительно здорово! tks ur! D: – JasonHuang 8 April 2015 в 09:35

Я использовал эту библиотеку cloning и нашел ее весьма полезной. Поскольку у него было несколько ограничений (мне нужен был более тонкий контроль над процессом клонирования: какое поле, в каком контексте и насколько глубоко нужно клонировать и т. Д.), Я создал расширенную версию. Вы управляете клонированием полей, аннотируя их в классе сущностей.

Чтобы получить его вкус, вот пример класса:

public class CloneMePlease {
    @Clone(Skip.class)
    String id3 = UUID.randomUUID().toString();

    @Clone(Null.class)
    String id4 = UUID.randomUUID().toString();

    @Clone(value = RandomUUID.class, groups=CustomActivationGroup1.class)
    String id5 = UUID.randomUUID().toString();

    @Clone.List({
            @Clone(groups=CustomActivationGroup2.class, value=Skip.class),
            @Clone(groups=CustomActivationGroup3.class, value=Copy.class)})
    Object activationGroupOrderTest = new Object();

    @Clone(LongIncrement.class)
    long version = 1l;

    @PostClone
    private void postClone(CloneMePlease original, @CloneInject CloneInjectedService service){
         //do stuff with the original source object in the context of the cloned object
         //you can inject whatewer service you want, from spring/guice to perform custom logic here
    }
}

Подробнее здесь: https://github.com/mnorbi/fluidity-cloning

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

2
ответ дан Norbert Madarász 15 August 2018 в 21:02
поделиться
10
ответ дан CorayThan 5 September 2018 в 20:30
поделиться
Другие вопросы по тегам:

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