Перейти к основному содержимому

Копирование HashMap в Java

· 4 мин. чтения

1. Обзор

В этом руководстве мы рассмотрим концепцию поверхностной и глубокой копии HashMap, а также несколько методов копирования HashMap в Java.

Мы также рассмотрим некоторые внешние библиотеки, которые могут помочь нам в конкретных случаях.

2. Мелкие и глубокие копии

Во-первых, давайте разберемся с концепцией мелких и глубоких копий в HashMaps .

2.1. Неглубокое копирование

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

Например, мы создадим класс Employee , а затем карту с экземплярами Employee в качестве значений:

public class Employee {
private String name;

// constructor, getters and setters
}
HashMap<String, Employee> map = new HashMap<>();
Employee emp1 = new Employee("John");
Employee emp2 = new Employee("Norman");
map.put("emp1", emp1);
map.put("emp2", emp2);

Теперь мы проверим, что исходная карта и ее неглубокая копия являются разными объектами:

HashMap<String, Employee> shallowCopy = // shallow copy implementation
assertThat(shallowCopy).isNotSameAs(map);

Поскольку это поверхностная копия, если мы изменим свойства экземпляра Employee , это повлияет как на исходную карту, так и на ее поверхностную копию:

emp1.setFirstName("Johny");
assertThat(shallowCopy.get("emp1")).isEqualTo(map.get("emp1"));

2.2. Глубокое копирование

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

Здесь явное изменение сопоставлений (ключ-значение) не повлияет на глубокую копию:

HashMap<String, Employee> deepCopy = // deep copy implementation

emp1.setFirstName("Johny");

assertThat(deepCopy.get("emp1")).isNotEqualTo(map.get("emp1"));

3. API -интерфейс хэш-карты

3.1. Использование конструктора HashMap C

`Параметризованный конструктор HashMap HashMap(Map<? extends K,? extends V> m)` обеспечивает быстрый способ поверхностного копирования всей карты:

HashMap<String, Employee> shallowCopy = new HashMap<String, Employee>(originalMap);

3.2. Использование Map.clone()

Подобно конструктору, метод HashMap # clone также создает быструю неглубокую копию:

HashMap<String, Employee> shallowCopy = originalMap.clone();

3.3. Использование Map.put()

HashMap можно легко скопировать, перебирая каждую запись и вызывая метод put () на другой карте:

HashMap<String, Employee> shallowCopy = new HashMap<String, Employee>();
Set<Entry<String, Employee>> entries = originalMap.entrySet();
for (Map.Entry<String, Employee> mapEntry : entries) {
shallowCopy.put(mapEntry.getKey(), mapEntry.getValue());
}

3.4. Использование Map.putAll()

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

HashMap<String, Employee> shallowCopy = new HashMap<>();
shallowCopy.putAll(originalMap);

Следует отметить, что put() и putAll() заменяют значения, если есть соответствующий ключ .

Также интересно отметить, что если мы посмотрим на конструктор HashMap , реализацию clone() и putAll() , мы обнаружим, что все они используют один и тот же внутренний метод для копирования записей — putMapEntries() .

4. Копирование HashMap с помощью потокового API Java 8

Мы можем использовать Java 8 Stream API для создания мелкой копии HashMap :

Set<Entry<String, Employee>> entries = originalMap.entrySet();
HashMap<String, Employee> shallowCopy = (HashMap<String, Employee>) entries.stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

5. Google Гуава

Используя карты Guava, мы можем легко создавать неизменяемые карты, а также отсортированную и бикарту. Чтобы сделать неизменяемую поверхностную копию любой из этих карт, мы можем использовать метод copyOf :

Map<String, Employee> map = ImmutableMap.<String, Employee>builder()
.put("emp1",emp1)
.put("emp2",emp2)
.build();
Map<String, Employee> shallowCopy = ImmutableMap.copyOf(map);

assertThat(shallowCopy).isSameAs(map);

6. Язык Apache Commons

Теперь в Java нет встроенных реализаций глубокого копирования. Таким образом, чтобы сделать глубокую копию, мы можем либо переопределить метод clone() , либо использовать метод сериализации-десериализации.

В Apache Commons есть SerializationUtils с методом clone() для создания глубокой копии. Для этого любой класс, который будет включен в глубокую копию, должен реализовать интерфейс Serializable :

public class Employee implements Serializable {
// implementation details
}

HashMap<String, Employee> deepCopy = SerializationUtils.clone(originalMap);

7. Заключение

В этом кратком руководстве мы рассмотрели различные методы копирования HashMap в Java, а также концепцию поверхностного и глубокого копирования для HashMap s.

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

Полный исходный код этих реализаций вместе с модульными тестами доступен в проекте GitHub .