我有一个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;
    }
}

我实现了一个克隆方法,以简单地返回完全独立于原始文件的声誉矩阵的单独副本。

我测试了这样的代码:
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));
    }
}

输出为:
2
2
3
3

这意味着我对矩阵1所做的每一次更改都反映在矩阵2上。
我几乎可以肯定putAll会创建副本。我究竟做错了什么?

最佳答案

documentation:

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)));
输出:
[0, 0, 0]
[1, 2, 3]

08-04 15:45