I have a Hashmap in which I wrote a class that deals with adding and retrieving values.
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;
}
}
I implemented a clone method to simply return a separate copy of ReputationMatrix totally independent from the original.
I tested the code like this:
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));
}
}
the output was:
2
2
3
3
Which means every change I apply to matrix1 is reflecting onto matrix2. I'm almost sure putAll does create copies. What am I doing wrong?
From the documentation:
putAll
Copies all of the mappings from the specified map to this map (optional operation). The effect of this call is equivalent to that of calling put(k, v) on this map once for each mapping from key k to value v in the specified map.
So it does not make copies of the objects, it only adds the mappings from the original map to the new map.
To do what you want, you would need to copy each value explicitly:
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)));
Output:
[0, 0, 0]
[1, 2, 3]