首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Hashmap分配给Hashmap

将Hashmap分配给Hashmap
EN

Stack Overflow用户
提问于 2012-07-02 23:17:00
回答 5查看 37.6K关注 0票数 17

我有一个哈希图,我想复制为其他用途。但每当我复制并重用它时,它也会改变原始的。为什么会这样呢?

代码语言:javascript
复制
    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);

提前感谢

代码语言:javascript
复制
    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;
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-07-02 23:18:41

您所做的不是创建地图的副本,而是创建对它的引用。当两个引用指向同一对象时,对其中一个的更改将反映在另一个对象中。

解决方案1:如果这是一个从一些简单类型到另一个类型的映射,那么您应该这样做:

代码语言:javascript
复制
Map<SomeType, OtherType> map1 = new HashMap<SomeType, OtherType>(original); 

这称为Copy Constructor。几乎所有标准的Collection和Map实现都有一个,这通常是克隆简单结构的最简单方法。只要SomeTypeOtherTypeimmutable (例如,Integer和其他Number类型、BooleanString,但不是集合、日期、映射、数组等),就可以很好地工作。

如果没有,正如其他回答者和评论者所指出的那样,您还需要复制map值。

解决方案2:这里有一个快速而肮脏的版本,应该是安全的:

代码语言:javascript
复制
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()));
}

但实际上,我喜欢Hunter提供深度复制方法的想法。下面是解决方案3:使用泛型参数的我自己的版本:

代码语言:javascript
复制
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;
}

你可以这样称呼它:

代码语言:javascript
复制
Map<Integer, Map<String, Object>> original=new HashMap<Integer, Map<String,Object>>();
// do stuff here
Map<Integer, Map<String, Object>> copy = deepCopy(original);

更新

我已经破解了一个类,它可以对Map、Collections和Array(原始的和其他的)执行深度克隆。用法:

代码语言:javascript
复制
Something clone = DeepClone.deepClone(original);

这就是它:

代码语言:javascript
复制
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;
    }
}
票数 54
EN

Stack Overflow用户

发布于 2012-07-02 23:20:18

通过这样做:

代码语言:javascript
复制
Map<Integer, Map<String, Object>> copy = originalMap;

..。您不是在复制map,而只是创建一个引用完全相同map的新变量,显然,您使用此变量所做的更改将反映在原始map中-它们指向内存中的同一对象。最好使用接收另一个地图作为参数的constructor复制原始地图:

代码语言:javascript
复制
Map<Integer, Map<String, Object>> copy;
copy = new HashMap<Integer, Map<String, Object>>(originalMap);

上面的代码将创建原始map的浅层副本,这意味着:如果您更改一个map中元素的值,更改将反映在另一个map中,但您可以自由添加/删除其中一个map中的元素,而其他map不会受到影响。如果这还不够好,则需要在复制时对map中的元素执行一次深度复制。

票数 7
EN

Stack Overflow用户

发布于 2012-07-02 23:25:36

一个简单而直接的解决方案是循环遍历Map中的值,并将它们复制到Map中:

代码语言:javascript
复制
Map<Integer, Map<String, Object>> map1;

//iterate over the map copying values into new map
for(Map.Entry entry : originalMap.entrySet())
{
   map1.put(entry.getKey(), new HashMap<String, Object>(entry.getValue()));
}

更好的解决方案是将其封装在一个方法中:

代码语言:javascript
复制
public static <K,J,V> Map<K, Map<J, V>> deepCopy(Map<K, Map<J, V>> original)
{
    Map<K, Map<J, V>> copy;

    //iterate over the map copying values into new map
    for(Map.Entry<K, Map<J, V>> entry : original.entrySet())
    {
       copy.put(entry.getKey(), new HashMap<J, V>(entry.getValue()));
    }

    return copy;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11296490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档