Мелкая копия карты в Java - PullRequest
       36

Мелкая копия карты в Java

102 голосов
/ 01 марта 2010

Насколько я понимаю, есть несколько способов (возможно, и других) для создания поверхностной копии Map в Java:

Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy;

// first way
shallowCopy = new HashMap<String, Object>(data);

// second way
shallowCopy = (Map<String, Object>) ((HashMap<String, Object>) data).clone();

Является ли один способ предпочтительнее другого, и если да, то почему?

Стоит отметить, что второй способ выдает предупреждение «Unchecked Cast». Поэтому вам нужно добавить @SuppressWarnings("unchecked"), чтобы обойти это, что немного раздражает (см. Ниже).

@SuppressWarnings("unchecked")
public Map<String, Object> getDataAsMap() {
    // return a shallow copy of the data map
    return (Map<String, Object>) ((HashMap<String, Object>) data).clone();
}

Ответы [ 3 ]

106 голосов
/ 01 марта 2010

Всегда лучше копировать, используя конструктор копирования. clone() в Java не работает (см. SO: Как правильно переопределить метод клонирования? ).

Джош Блох о дизайне - конструктор копирования и клонирование

Если вы читали статью о клонировании в моей книге, особенно если вы читаете между строк, вы поймете, что я думаю, clone глубоко нарушен. [...] Обидно, что Cloneable сломан, но это случается.

Блох (который, кстати, разработал и внедрил платформу Collection) даже сказал, что он предоставляет метод clone() только «потому, что люди этого ожидают». На самом деле он НЕ рекомендует вообще его использовать.


Я думаю, что более интересная дискуссия о том, лучше ли конструктор копирования, чем фабрика копий, но это совсем другое обсуждение.

58 голосов
/ 01 февраля 2013

Ни то, ни другое: конструктор , на который вы ссылаетесь, определен для HashMap реализации Map (как и для других) но не для самого интерфейса Map (например, рассмотрим реализацию интерфейса Map * Provider : вы не найдете этот конструктор).

С другой стороны, не рекомендуется использовать метод clone(), как объяснил Джош Блох.

В отношении интерфейса Map (и вашего вопроса, в котором вы спрашиваете, как скопировать карту, а не HashMap), вы должны использовать Map # putAll () :

Копирует все сопоставления с указанной карты на эту карту. (необязательная операция). Эффект этого вызова эквивалентен вызывая put (k, v) на этой карте один раз для каждого отображения от ключа k до значение v в указанной карте.

* * Пример тысяча двадцать-один: * * 1 022
// HashMap here, but it works for every implementation of the Map interface
Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy = new HashMap<String, Object>();

shallowCopy.putAll(data);
11 голосов
/ 04 февраля 2015

Скопируйте карту, не зная ее реализации:

static final Map shallowCopy(final Map source) throws Exception {
    final Map newMap = source.getClass().newInstance();
    newMap.putAll(source);
    return newMap;
}
...