I have a hashmap which I want to copy for other use. But whenever I copy it and reuse it, it also changes the original one. Why is that?
do {
What you did was not to create a copy of the map, but of the reference to it. when two references point to the same object, changes to one will reflect in the other.
Solution 1: If this was a Map from some simple type to another, you would do this instead:
Map map1 = new HashMap(original);
This is called a Copy Constructor. Almost All standard Collection and Map implementations have one, and it's usually the simplest way to clone a simple structure.
This will work fine as long as SomeType and OtherType are immutable (e.g. Integer and other Number types, Boolean, String, but not Collections, Dates, Maps, Arrays etc.)
If not, as other answerers and commenters have pointed out, you also need to copy the map values.
Solution 2: Here's a quick and dirty version that should be safe:
Map> original=new HashMap>();
Map> copy =
new HashMap>();
for(Entry> entry : original.entrySet()){
copy.put(entry.getKey(), new HashMap(entry.getValue()));
}
But actually, I like Hunter's idea of providing a deep copy method. So here's Solution 3: my own version using generic parameters:
public static Map> deepCopy(
Map> original){
Map> copy = new HashMap>();
for(Entry> entry : original.entrySet()){
copy.put(entry.getKey(), new HashMap(entry.getValue()));
}
return copy;
}
You can call it like this:
Map> original=new HashMap>();
// do stuff here
Map> copy = deepCopy(original);
Update
I've hacked together a class that performs deep cloning for Maps, Collections and Arrays (primitive and otherwise). Usage:
Something clone = DeepClone.deepClone(original);
Here it is:
public final class DeepClone {
private DeepClone(){}
public static X deepClone(final X input) {
if (input == null) {
return input;
} else if (input instanceof Map, ?>) {
return (X) deepCloneMap((Map, ?>) input);
} else if (input instanceof Collection>) {
return (X) deepCloneCollection((Collection>) input);
} else if (input instanceof Object[]) {
return (X) deepCloneObjectArray((Object[]) input);
} else if (input.getClass().isArray()) {
return (X) clonePrimitiveArray((Object) input);
}
return input;
}
private static Object clonePrimitiveArray(final Object input) {
final int length = Array.getLength(input);
final Object copy = Array.newInstance(input.getClass().getComponentType(), length);
// deep clone not necessary, primitives are immutable
System.arraycopy(input, 0, copy, 0, length);
return copy;
}
private static E[] deepCloneObjectArray(final E[] input) {
final E[] clone = (E[]) Array.newInstance(input.getClass().getComponentType(), input.length);
for (int i = 0; i < input.length; i++) {
clone[i] = deepClone(input[i]);
}
return clone;
}
private static Collection deepCloneCollection(final Collection input) {
Collection clone;
// this is of course far from comprehensive. extend this as needed
if (input instanceof LinkedList>) {
clone = new LinkedList();
} else if (input instanceof SortedSet>) {
clone = new TreeSet();
} else if (input instanceof Set) {
clone = new HashSet();
} else {
clone = new ArrayList();
}
for (E item : input) {
clone.add(deepClone(item));
}
return clone;
}
private static Map deepCloneMap(final Map map) {
Map clone;
// this is of course far from comprehensive. extend this as needed
if (map instanceof LinkedHashMap, ?>) {
clone = new LinkedHashMap();
} else if (map instanceof TreeMap, ?>) {
clone = new TreeMap();
} else {
clone = new HashMap();
}
for (Entry entry : map.entrySet()) {
clone.put(deepClone(entry.getKey()), deepClone(entry.getValue()));
}
return clone;
}
}