1. Обзор
В этом уроке мы рассмотрим концепцию неглубокой vs глубокой копии | HashMap | вместе с несколькими методами копирования HashMap в Java.
Мы также рассмотрим некоторые внешние библиотеки, которые могут помочь нам в конкретных случаях.
2. Неглубокие и глубокие копии
Во-первых, давайте разберемся в концепции неглубоких и глубоких копий в HashMaps .
2.1. Мелкая копия
Неглубокая копия Хэш-карта это новый Хэш-карта с сопоставлениями с теми же объектами ключей и значений, что и оригинал Хэш-карта .
Например, мы создадим класс Employee , а затем карту с экземплярами Employee в качестве значений:
public class Employee { private String name; // constructor, getters and setters }
HashMapmap = new HashMap<>(); Employee emp1 = new Employee("John"); Employee emp2 = new Employee("Norman"); map.put("emp1", emp1); map.put("emp2", emp2);
Теперь мы проверим, что исходная карта и ее неглубокая копия являются разными объектами:
HashMapshallowCopy = // shallow copy implementation assertThat(shallowCopy).isNotSameAs(map);
Поскольку это неглубокая копия, если мы изменим свойства экземпляра Employee , это повлияет как на исходную карту, так и на ее неглубокую копию:
emp1.setFirstName("Johny"); assertThat(shallowCopy.get("emp1")).isEqualTo(map.get("emp1"));
2.2. Глубокое копирование
Глубокая копия HashMap – это новая HashMap , которая глубоко копирует все сопоставления. Поэтому он создает новые объекты для всех ключей, значений и сопоставлений.
Здесь явное изменение сопоставлений (значений ключей) не повлияет на глубокую копию:
HashMapdeepCopy = // deep copy implementation emp1.setFirstName("Johny"); assertThat(deepCopy.get("emp1")).isNotEqualTo(map.get("emp1"));
3. API HashMap
3.1. Использование конструктора HashMap
HashMap параметризованный конструктор HashMap(Map extends K,? extends V> m) обеспечивает быстрый способ быстрого копирования всей карты: extends K,? extends V> m)
HashMapshallowCopy = new HashMap (originalMap);
3.2. Использование Map.clone()
Подобно конструктору, метод HashMap # clone также создает быструю неглубокую копию:
HashMapshallowCopy = originalMap.clone();
3.3. Использование Map.put()
HashMap можно легко скопировать, выполнив итерацию по каждой записи и вызвав метод put() на другой карте:
HashMapshallowCopy = new HashMap (); Set > entries = originalMap.entrySet(); for (Map.Entry mapEntry : entries) { shallowCopy.put(mapEntry.getKey(), mapEntry.getValue()); }
3.4. Использование Map.putAll()
Вместо того, чтобы перебирать все записи, мы можем использовать метод putAll () , который копирует все сопоставления за один шаг:
HashMapshallowCopy = new HashMap<>(); shallowCopy.putAll(originalMap);
Следует отметить, что put() и putAll() заменяют значения, если есть соответствующий ключ .
Также интересно отметить, что, если мы посмотрим на конструктор HashMap , clone () и putAll() реализации, мы обнаружим, что все они используют один и тот же внутренний метод для копирования записей — putMapEntries() .
4. Копирование хэш-карты с помощью API потока Java 8
Мы можем использовать Java 8 Stream API для создания неглубокой копии HashMap :
Set> entries = originalMap.entrySet(); HashMap shallowCopy = (HashMap ) entries.stream() .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
5. Google Гуава
Используя Guava Maps, мы можем легко создавать неизменяемые карты, а также отсортированное и растровое изображение. Чтобы сделать неизменяемую неглубокую копию любой из этих карт, мы можем использовать метод copyOf :
Mapmap = ImmutableMap. builder() .put("emp1",emp1) .put("emp2",emp2) .build(); Map shallowCopy = ImmutableMap.copyOf(map); assertThat(shallowCopy).isSameAs(map);
6. Apache Commons Lang
Теперь в Java нет встроенных реализаций глубокого копирования. Таким образом, чтобы сделать глубокую копию, мы можем либо переопределить метод clone () , либо использовать метод сериализации-десериализации.
Apache Commons имеет SerializationUtils с методом clone() для создания глубокой копии. Для этого любой класс, который будет включен в deep copy, должен реализовать Сериализуемый интерфейс:
public class Employee implements Serializable { // implementation details } HashMapdeepCopy = SerializationUtils.clone(originalMap);
7. Заключение
В этом кратком руководстве мы рассмотрели различные методы копирования HashMap в Java, а также концепцию неглубокого и глубокого копирования для HashMap s.
Кроме того, мы изучили некоторые внешние библиотеки, которые очень удобны для создания неглубоких и глубоких копий.
Полный исходный код этих реализаций вместе с модульными тестами доступен в проекте GitHub .