1. Información general
En este tutorial, exploraremos el concepto de una copia superficial o profunda de un HashMap junto con varias técnicas para copiar un HashMap en Java.
También consideraremos algunas de las bibliotecas externas que pueden ayudarnos en casos específicos.
2. Copias superficiales vs profundas
En primer lugar, comprendamos el concepto de copias superficiales y profundas en HashMaps .
2.1. Copia superficial
Una copia superficial de un HashMap es un nuevo HashMap con asignaciones a los mismos objetos de clave y valor que el HashMap original .
Por ejemplo, crearemos una clase de Empleado y luego un mapa con instancias de Empleado como valores:
public class Employee { private String name; // constructor, getters and setters }
HashMap map = new HashMap(); Employee emp1 = new Employee("John"); Employee emp2 = new Employee("Norman"); map.put("emp1", emp1); map.put("emp2", emp2);
Ahora, verificaremos que el mapa original y su copia superficial son objetos diferentes:
HashMap shallowCopy = // shallow copy implementation assertThat(shallowCopy).isNotSameAs(map);
Debido a que esta es una copia superficial, si cambiamos las propiedades de una instancia de Empleado , afectará tanto al mapa original como a su copia superficial:
emp1.setFirstName("Johny"); assertThat(shallowCopy.get("emp1")).isEqualTo(map.get("emp1"));
2.2. Copia profunda
Una copia profunda de un HashMap es un nuevo HashMap que copia profundamente todas las asignaciones. Por lo tanto, crea nuevos objetos para todas las claves, valores y asignaciones.
Aquí, la modificación explícita de las asignaciones (pares clave-valor) no afectará a la copia profunda:
HashMap deepCopy = // deep copy implementation emp1.setFirstName("Johny"); assertThat(deepCopy.get("emp1")).isNotEqualTo(map.get("emp1"));
3. API de HashMap
3.1. Usando el HashMap C onstructor
HashMap 's constructor parametrizado HashMap (Mapa m) ofrece una forma rápida de poca profundidad copiar un mapa completo:
HashMap shallowCopy = new HashMap(originalMap);
3.2. Usando Map.clone ()
Similar al constructor, el método de clonación HashMap # también crea una copia superficial rápida:
HashMap shallowCopy = originalMap.clone();
3.3. Usando Map.put ()
Un HashMap se puede copiar fácilmente iterando sobre cada entrada y llamando al método put () en otro mapa:
HashMap shallowCopy = new HashMap(); Set
entries = originalMap.entrySet(); for (Map.Entry mapEntry : entries) { shallowCopy.put(mapEntry.getKey(), mapEntry.getValue()); }
3.4. Usando Map.putAll ()
En lugar de iterar a través de todas las entradas, podemos usar el método putAll () , que copia superficialmente todas las asignaciones en un solo paso:
HashMap shallowCopy = new HashMap(); shallowCopy.putAll(originalMap);
Debemos tener en cuenta que put () y putAll () reemplazan los valores si hay una clave coincidente .
También es interesante notar que, si miramos el constructor de HashMap , clone () y la implementación de putAll () , encontraremos que todos usan el mismo método interno para copiar entradas - putMapEntries () .
4. Copia de HashMap con la API de secuencia de Java 8
Podemos usar la API de Java 8 Stream para crear una copia superficial de un HashMap :
Set
entries = originalMap.entrySet(); HashMap shallowCopy = (HashMap) entries.stream() .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
5. Google Guayaba
Usando Guava Maps, podemos crear fácilmente mapas inmutables, junto con el mapa ordenado y bi. Para hacer una copia superficial e inmutable de cualquiera de estos mapas, podemos usar el método copyOf :
Map map = ImmutableMap.builder() .put("emp1",emp1) .put("emp2",emp2) .build(); Map shallowCopy = ImmutableMap.copyOf(map); assertThat(shallowCopy).isSameAs(map);
6. Apache Commons Lang
Ahora, Java no tiene implementaciones integradas de copia profunda. Entonces, para hacer una copia profunda, podemos anular el método clone () o usar una técnica de serialización-deserialización.
Apache Commons tiene SerializationUtils con un método clone () para crear una copia profunda. Para esto, cualquier clase que se incluya en una copia profunda debe implementar la interfaz serializable :
public class Employee implements Serializable { // implementation details } HashMap deepCopy = SerializationUtils.clone(originalMap);
7. Conclusión
En este tutorial rápido, hemos visto varias técnicas para copiar un HashMap en Java, junto con el concepto de copia superficial y profunda para HashMap .
Además, exploramos algunas de las bibliotecas externas que son bastante útiles para crear copias superficiales y profundas.
El código fuente completo de estas implementaciones junto con las pruebas unitarias están disponibles en el proyecto GitHub.