Мелкая копия карты в Java
Как я понимаю, существует несколько способов (возможно, других) создать небольшую копию 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();
}
Ответы
Ответ 1
Всегда лучше копировать, используя конструктор копирования. clone()
в Java не работает (см. SO: Как правильно переопределить метод клонирования?).
Джош Блох по дизайну - Копировать конструктор против клонирования
Если вы прочитали статью о клонировании в моей книге, особенно если вы читаете между строками, вы будете знать, что я думаю, что clone
глубоко нарушен. [...] Позор, что Cloneable
сломан, но это происходит.
Блох (который, кстати, разработал и реализовал структуру Collection), даже пошел дальше, сказав, что он только предоставляет метод clone()
только потому, что люди этого ожидают ". Он НЕ рекомендует вообще его использовать.
Я думаю, что более интересная дискуссия заключается в том, что конструктор копирования лучше, чем копия factory, но это совсем другое обсуждение.
Ответ 2
Ни один из двух: конструктор о котором вы говорите, определен для HashMap реализация Map (как и для других), но не для самого интерфейса карты (например, рассмотрим Provider реализации интерфейса карты: вы не найдете этот конструктор).
С другой стороны, не рекомендуется использовать метод clone()
, как объяснил Джош Блох.
В отношении интерфейса карты (и вашего вопроса, в котором вы спрашиваете, как скопировать карту, а не HashMap), вы должны использовать Map # putAll():
Копирует все сопоставления с указанной карты на эту карту (дополнительная операция). Эффект этого вызова эквивалентен эффекту вызов put (k, v) на этой карте один раз для каждого отображения из ключа k в значение v на указанной карте.
Пример:
// 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);
Ответ 3
Скопируйте карту, не зная ее реализации:
static final Map shallowCopy(final Map source) throws Exception {
final Map newMap = source.getClass().newInstance();
newMap.putAll(source);
return newMap;
}