Assigning Hashmap to Hashmap

java

Solution

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<SomeType, OtherType> map1 = new HashMap<SomeType, OtherType>(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<Integer, Map<String, Object>> original=new HashMap<Integer, Map<String,Object>>();
Map<Integer, Map<String, Object>> copy = 
        new HashMap<Integer, Map<String, Object>>();
for(Entry<Integer, Map<String, Object>> entry : original.entrySet()){
    copy.put(entry.getKey(), new HashMap<String, Object>(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 <K1, K2, V> Map<K1, Map<K2, V>> deepCopy(
    Map<K1, Map<K2, V>> original){

    Map<K1, Map<K2, V>> copy = new HashMap<K1, Map<K2, V>>();
    for(Entry<K1, Map<K2, V>> entry : original.entrySet()){
        copy.put(entry.getKey(), new HashMap<K2, V>(entry.getValue()));
    }
    return copy;
}

You can call it like this:

Map<Integer, Map<String, Object>> original=new HashMap<Integer, Map<String,Object>>();
// do stuff here
Map<Integer, Map<String, Object>> 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> 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> 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 <E> Collection<E> deepCloneCollection(final Collection<E> input) {
        Collection<E> clone;
        // this is of course far from comprehensive. extend this as needed
        if (input instanceof LinkedList<?>) {
            clone = new LinkedList<E>();
        } else if (input instanceof SortedSet<?>) {
            clone = new TreeSet<E>();
        } else if (input instanceof Set) {
            clone = new HashSet<E>();
        } else {
            clone = new ArrayList<E>();
        }

        for (E item : input) {
            clone.add(deepClone(item));
        }

        return clone;
    }

    private static <K, V> Map<K, V> deepCloneMap(final Map<K, V> map) {
        Map<K, V> clone;
        // this is of course far from comprehensive. extend this as needed
        if (map instanceof LinkedHashMap<?, ?>) {
            clone = new LinkedHashMap<K, V>();
        } else if (map instanceof TreeMap<?, ?>) {
            clone = new TreeMap<K, V>();
        } else {
            clone = new HashMap<K, V>();
        }

        for (Entry<K, V> entry : map.entrySet()) {
            clone.put(deepClone(entry.getKey()), deepClone(entry.getValue()));
        }

        return clone;
    }
}

Problem

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 { Map<Integer, Map<String, Object>> map1 = originalMap; //at the second iteration originalMap is the same as map1 of the last iteration, //eventhough the change was nog accepted; //do something with map1 (change value); if(change is accepted) { originalMap = map1; } } while(iteration < 10); ``` Thanks in advance ``` public static <Integer,String, Schedule>Map<Integer, Map<String, Schedule>> deepCopy(Map<Integer, Map<String, Schedule>> original) { Map<Integer, Map<String, Schedule>> copy = new HashMap<Integer, Map<String, Schedule>>(); for (Map.Entry<Integer, Map<String, Schedule>> entry : original.entrySet()) { copy.put(entry.getKey(), deepCopy2(entry.getValue())); } return copy; } public static <String, Schedule>Map<String, Schedule> deepCopy2(Map<String, Schedule> original) { Map<String, Schedule> copy = new HashMap<String, Schedule>(); for (Map.Entry<String, Schedule> entry : original.entrySet()) { copy.put(entry.getKey(), entry.getValue()); } return copy; } ```

Original source

Related problems