Copiando um HashMap em Java

Copiando um HashMap em Java

1. Visão geral

Neste tutorial, vamos explorar o conceito de um raso vsdeep copy de aHashMap junto com várias técnicas para copiar aHashMap em Java.

Também consideraremos algumas das bibliotecas externas que podem nos ajudar em casos específicos.

2. Cópias superficiais vs profundas

Em primeiro lugar, vamos entender o conceito de cópias superficiais e profundas emHashMaps.

2.1. Cópia rasa

Uma cópia superficial deHashMap é um novoHashMap com mapeamentos para a mesma chave e objetos de valor que oHashMap original.

Por exemplo, vamos criar uma classeEmployee e, em seguida, um mapa com instânciasEmployee 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);

Agora, vamos verificar se o mapa original e sua cópia superficial são objetos diferentes:

HashMap shallowCopy = // shallow copy implementation
assertThat(shallowCopy).isNotSameAs(map);

Como esta é uma cópia superficial, se alterarmos as propriedades de uma instânciaEmployee, isso afetará o mapa original e sua cópia superficial:

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

2.2. Cópia profunda

A deep copy of a HashMap is a new HashMap that deeply copies all the mappings. Portanto, ele cria novos objetos para todas as chaves, valores e mapeamentos.

Aqui, a modificação explícita dos mapeamentos (valores-chave) não afetará a cópia detalhada:

HashMap deepCopy = // deep copy implementation

emp1.setFirstName("Johny");

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

3. APIHashMap

3.1. Usando o sonstrutorHashMapC

construtor parametrizado deHashMapHashMap(Map<? extends K,? extends V> m)provides a quick way to shallow copy an entire map:

HashMap shallowCopy = new HashMap(originalMap);

3.2. UsandoMap.clone()

Semelhante ao construtor, o métodoHashMap #clone também cria uma cópia superficial rápida:

HashMap shallowCopy = originalMap.clone();

3.3. UsandoMap.put()

UmHashMap pode ser facilmente copiado superficialmente iterando sobre cada entrada e chamando o métodoput() em outro mapa:

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

3.4. UsandoMap.putAll()

Em vez de iterar por todas as entradas, podemos usar o métodoputAll(), que copia superficialmente todos os mapeamentos em uma etapa:

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

Devemos observar queput() and putAll() replace the values if there is a matching key.

Também é interessante notar que, se olharmos para o construtor deHashMap,clone() e a implementação deputAll(), descobriremos que todos eles usam o mesmo método interno para copiar entradas -putMapEntries().

4. CopiandoHashMap usando a API Java 8Stream

Podemos usarJava 8 Stream API para criar uma cópia superficial de umHashMap:

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

5. Google Guava

UsandoGuava Maps,, podemos criar facilmente mapas imutáveis, junto com o mapa classificado e bi. Para fazer uma cópia imutável e superficial de qualquer um desses mapas, podemos usar o métodocopyOf:

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

assertThat(shallowCopy).isSameAs(map);

6. Apache Commons Lang

Now, Java doesn’t have any built-in deep copy implementations. Portanto, para fazer uma cópia profunda, podemos substituir o métodoclone() ou usar uma técnica de serialização-desserialização.

O Apache Commons temSerializationUtils com um métodoclone() para criar uma cópia profunda. Para isso, qualquer classe a ser incluída na cópia profunda deve implementar a interfaceSerializable:

public class Employee implements Serializable {
    // implementation details
}

HashMap deepCopy = SerializationUtils.clone(originalMap);

7. Conclusão

Neste tutorial rápido, vimos várias técnicas para copiar umHashMap em Java, junto com o conceito de cópia superficial e profunda paraHashMaps.

Além disso, exploramos algumas das bibliotecas externas que são bastante úteis para criar cópias superficiais e profundas.

O código-fonte completo dessas implementações junto com os testes de unidade estão disponíveis no projetoGitHub.