Je dois 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. c'est-à-dire lorsque je retire quelque chose du List<MySpecialClass>
à partir de la copie, il reste dans le List<MySpecialClass>
dans la version originale.
Si je comprends bien, ces deux méthodes créent une copie superficielle qui n'est pas ce que je veux:
mapCopy = new HashMap<>(originalMap);
mapCopy = (HashMap) originalMap.clone();
Ai-je raison?
Existe-t-il une meilleure façon de le faire que de simplement parcourir toutes les clés et tous les éléments de la liste et de les copier manuellement?
Vous avez raison qu'une copie superficielle ne répondra pas à vos besoins. Il aura des copies des List
s de votre carte d'origine, mais ces List
s feront référence aux mêmes objets List
, de sorte qu'une modification à un List
d'un HashMap
apparaîtra dans le List
correspondant de l'autre HashMap
.
Aucune copie approfondie n'est fournie pour un HashMap
en Java, vous devrez donc parcourir toutes les entrées et put
les dans le nouveau HashMap
. Mais vous devez également faire une copie du List
à chaque fois également. Quelque chose comme ça:
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 vos objets MySpecialClass
individuels et que les modifications ne se reflètent pas dans les List
s de vos HashMap
copiés, vous devrez en faire de nouvelles copies aussi.
Cela nécessite malheureusement une itération. Mais c'est assez trivial avec Java 8 flux:
mapCopy = map.entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> new ArrayList(e.getValue()));
Edit: dans les versions ultérieures de Java, e -> List.copyOf(e.getValue())
serait préféré.
Sérialiser en json et désérialiser ensuite:
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 devrez peut-être écrire un désérialiseur personnalisé .
Vous pouvez essayer le clonage en profondeur. Jetez un œil par exemple à https://code.google.com/p/cloning/
Vous créez une copie du HashMap lui-même, donc la modification de la copie du HashMap ne changera pas le HashMap d'origine (c'est-à-dire l'ajout ou la suppression d'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 le même, qu'il soit extrait de la première ou de la deuxième carte.
Ainsi, il n'y a qu'une seule copie de cette liste, référencée par les deux cartes: la modification de la liste la modifie quelle que soit la référence que vous utilisez pour y accéder.
Si vous voulez que la liste réelle soit une copie distincte, vous devrez faire comme vous l'avez dit: parcourir le jeu d'entrées du HashMap et créer une copie de chaque liste manuellement, en l'ajoutant à la nouvelle carte au fur et à mesure.
S'il existe un meilleur moyen que cela, je ne sais pas ce que c'est.