java HashMap.putall是否克隆所有元素?

java HashMap.putall是否克隆所有元素?,java,hashmap,cloning,Java,Hashmap,Cloning,我有一个Hashmap,我在其中编写了一个类,用于添加和检索值 class ReputationMatrix { private HashMap < Integer, int[] > repMatrix; public ReputationMatrix() { repMatrix = new HashMap < Integer, int[] > (); } public void addrating(int no

我有一个Hashmap,我在其中编写了一个类,用于添加和检索值

class ReputationMatrix
{
    private HashMap < Integer, int[] > repMatrix;

    public ReputationMatrix()
    {
        repMatrix = new HashMap < Integer, int[] > ();
    }

    public void addrating(int nodeId, boolean rating)
    {
        int[] alphaBeta;

        if (repMatrix.containsKey(nodeId))
        {
            alphaBeta = repMatrix.get(nodeId);

            if (rating == true)
            {
                alphaBeta[0] = alphaBeta[0] + 1;
            }
            else
            {
                alphaBeta[1] = alphaBeta[1] + 1;
            }

            repMatrix.put(nodeId, alphaBeta);
        }
        else
        {
            alphaBeta = new int[2];

            if (rating == true)
            {
                alphaBeta[0] = 2;
                alphaBeta[1] = 1;
            }
            else
            {
                alphaBeta[0] = 1;
                alphaBeta[1] = 2;
            }

            repMatrix.put(nodeId, alphaBeta);

        }
    }

    public int[] getNodeIds()
    {
        int[] nodeIds = new int[repMatrix.size()];
        int index = 0;

        for (int key: repMatrix.keySet())
        {
            nodeIds[index] = key;
            index++;
        }

        return nodeIds;
    }

    public int getAlpha(int nodeId)
    {
        return repMatrix.get(nodeId)[0];
    }

    public int getBeta(int nodeId)
    {
        return repMatrix.get(nodeId)[1];
    }

    public ReputationMatrix clone()
    {
        ReputationMatrix matrixClone = new ReputationMatrix();
        matrixClone.repMatrix.putAll(this.repMatrix);
        return matrixClone;
    }
}
结果是:

2
2
3
3
这意味着我对matrix1所做的每一个改变都会反映在matrix2上。 我几乎可以肯定putAll确实创建了副本。我做错了什么?

来自:

putAll

将所有映射从指定映射复制到此映射(可选操作)。对于指定映射中从键k到值v的每个映射,此调用的效果相当于在该映射上调用put(k,v)一次

因此它不复制对象,只将原始贴图中的映射添加到新贴图中

要执行所需操作,需要显式复制每个值:

Map<Integer, int[]> originalMatrix = new HashMap<>();
int[] original = {1, 2, 3};
originalMatrix.put(1, original);
Map<Integer, int[]> newMatrix = new HashMap<>();
    
for (Map.Entry<Integer, int[]> entry : originalMatrix.entrySet()) {
    newMatrix.put(entry.getKey(), entry.getValue().clone());
}

Arrays.fill(original, 0);

System.out.println(Arrays.toString(original));
System.out.println(Arrays.toString(newMatrix.get(1)));

putAll
不会创建键和值的副本。它为传递给它的每个键/值对调用
put
,并且
put
不会创建副本。

否,
putAll()
不会将元素克隆到映射。它只是将引用复制到它们,这样就有两个引用变量指向堆中的同一个对象。这称为浅复制。如果要克隆所有元素(deepcopy),必须执行以下操作:

public class Main
{
    /**
     * @param args
     */
    public static void main(String[] args)
    {
        ReputationMatrix matrix1 = new ReputationMatrix();
        matrix1.addrating(18, true);

        ReputationMatrix matrix2 = matrix1.clone();

        System.out.println(matrix1.getAlpha(18));
        System.out.println(matrix2.getAlpha(18));

        matrix1.addrating(18, true);

        System.out.println(matrix1.getAlpha(18));
        System.out.println(matrix2.getAlpha(18));
    }
}
Map<K,V> original = new HashMap<K,V>();
Map<K,V> clone = new HashMap<K,V>();
for(Map.Entry<K,V> entry : original.entrySet) {
  clone.put(entry.getKey(), entry.getValue().clone());
}
Map original=newhashmap();
Map clone=new HashMap();
for(Map.Entry:original.entrySet){
clone.put(entry.getKey(),entry.getValue().clone());
}

如您所见,没有副本

 /**
 * Copies all of the mappings from the specified map to this map.
 * These mappings will replace any mappings that this map had for
 * any of the keys currently in the specified map.
 *
 * @param m mappings to be stored in this map
 * @throws NullPointerException if the specified map is null
 */
public void putAll(Map<? extends K, ? extends V> m) {
    int numKeysToBeAdded = m.size();
    if (numKeysToBeAdded == 0)
        return;

    /*
     * Expand the map if the map if the number of mappings to be added
     * is greater than or equal to threshold.  This is conservative; the
     * obvious condition is (m.size() + size) >= threshold, but this
     * condition could result in a map with twice the appropriate capacity,
     * if the keys to be added overlap with the keys already in this map.
     * By using the conservative calculation, we subject ourself
     * to at most one extra resize.
     */
    if (numKeysToBeAdded > threshold) {
        int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
        if (targetCapacity > MAXIMUM_CAPACITY)
            targetCapacity = MAXIMUM_CAPACITY;
        int newCapacity = table.length;
        while (newCapacity < targetCapacity)
            newCapacity <<= 1;
        if (newCapacity > table.length)
            resize(newCapacity);
    }

    for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
        Map.Entry<? extends K, ? extends V> e = i.next();
        put(e.getKey(), e.getValue());
    }
} 
/**
*将指定映射中的所有映射复制到此映射。
*这些映射将替换此映射用于的所有映射
*指定映射中当前的任何键。
*
*@param m要存储在此映射中的映射
*@如果指定的映射为null,则会引发NullPointerException
*/

public void putAll(MapJava中没有深度副本。如果需要,必须通过递归调用
clone()
对其进行编码

还要注意,数组是对象,因此
int[]
in

private HashMap < Integer, int[] > repMatrix;

.putAll()
从不进行“深度复制”;它只做浅拷贝。你从哪里读到它做了深拷贝?put和putall只存储对对象的引用。也许当时我错了。所以我克隆Hashmap的唯一方法是循环遍历所有键并克隆数组?在Java中,你永远不会自动获得拷贝,它必须是显式的。这有一个根本原因:复制对象图是一个定义不正确的概念,在一般情况下无法解决。您是指entry.get[Key | Value].clone(),是吗?是的!谢谢您的提示:)我只需要克隆值,使用与实际使用的密钥散列相同的密钥没有问题。如果您解释代码中证明没有创建副本的部分,这将是一个很好的答案。我有以下数据集
HashMap
,当我使用putAll时,我看起来像是复制的对象而不是值。因为第一个的变化会影响第二个
 for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
        Map.Entry<? extends K, ? extends V> e = i.next();
        put(e.getKey(), e.getValue());
    }
private HashMap < Integer, int[] > repMatrix;
    if (repMatrix.containsKey(nodeId)) {
        alphaBeta = repMatrix.get(nodeId);

        if (rating == true) {
            alphaBeta[0] = alphaBeta[0] + 1;
        }
        else {
            alphaBeta[1] = alphaBeta[1] + 1;
        }

        //repMatrix.put(nodeId, alphaBeta); <= not needed
    }