Comment copier HashMap (et non shallow copy) en Java
j'ai besoin de faire une copie de HashMap<Integer, List<MySpecialClass> >
mais quand je change quelque chose dans la copie je veux que l'original reste le même. j'.e quand j'ai supprimer quelque chose de la List<MySpecialClass>
à partir de la copie qu'il reste dans le List<MySpecialClass>
dans l'original.
si je le comprends bien, ces deux méthodes ne créent qu'une copie superficielle qui n'est pas ce que je veux:
mapCopy = new HashMap<>(originalMap);
mapCopy = (HashMap) originalMap.clone();
Suis-je le droit?
Est-il une meilleure façon de le faire que de simplement itérer sur toutes les touches et tous les éléments de la liste et copie manuellement?
5 réponses
vous avez raison qu'une copie superficielle ne répond pas à vos exigences. Il y aura des copies du List
s à partir de votre carte d'origine, mais ceux List
S fera référence à la même List
objets, de sorte qu'une modification à un List
d'un HashMap
apparaîtra dans le List
de l'autre HashMap
.
il n'y a pas de copie profonde fournie pour un HashMap
en Java, donc vous devrez toujours boucler toutes les entrées et put
dans la HashMap
. Mais vous devez également faire une copie du List
à chaque fois aussi. Quelque chose comme ceci:
public static HashMap<Integer, List<MySpecialClass>> copy(
HashMap<Integer, List<MySpecialClass>> original)
{
HashMap<Integer, List<MySpecialClass>> copy = new HashMap<Integer, List<MySpecialClass>>();
for (Map.Entry<Integer, List<MySpecialClass>> entry : original.entrySet())
{
copy.put(entry.getKey(),
// Or whatever List implementation you'd like here.
new ArrayList<MySpecialClass>(entry.getValue()));
}
return copy;
}
Si vous souhaitez modifier votre MySpecialClass
les objets, et les changements figurent pas dans le List
s de votre copié HashMap
, vous devrez alors faire de nouvelles copies de trop.
cela nécessite malheureusement une itération. Mais C'est assez trivial avec Java 8 streams:
mapCopy = map.entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> new ArrayList(e.getValue()));
vous pouvez essayer le clonage profond. Regardez par exemple https://code.google.com/p/cloning/
vous faites une copie du HashMap lui-même, donc changer la copie du HashMap ne changera pas le HashMap original (c.-à-d. ajouter ou supprimer des entrées), mais parce que les objets que vous avez stockés ne sont pas des types primitifs, la liste que vous récupérez avec une clé donnée sera la même si récupéré à partir de la première ou de la deuxième carte.
ainsi, il n'y a toujours qu'une seule copie de cette liste, référencée par les deux cartes: changer la liste change peu importe quelle référence vous utilisez pour accéder il.
si vous voulez que la liste actuelle soit une copie séparée, vous devrez faire comme vous l'avez dit: itérer sur le jeu d'entrée de HashMap et créer une copie de chaque liste manuellement, en l'ajoutant à la nouvelle carte au fur et à mesure.
S'il y a un meilleur moyen que cela, je ne sais pas ce que c'est.
Sérialiser en json et désérialiser par la suite:
Map<String, Object> originalMap = new HashMap<>();
String json = new Gson().toJson(originalMap);
Map<String, Object> mapCopy = new Gson().fromJson(
json, new TypeToken<Map<String, Object>>() {}.getType());
pour les classes spéciales vous pourriez avoir besoin de écrire une coutume deserializer.