Hello I'll go straight into the problem. I know that in HashMaps in java the valueSet stores REFERENCE, that means that if I change that reference the specific value of that key should change too since both refer to the same object.
But I had some problems with my application so I tried to debug it to see how HashMap works practically. So I coded this mini proggram:
class Test
{
private final static HashMap<Integer, String> test = new HashMap<>();
public static void main(String[] args)
{
String s = "String";
test.put(1, s);
test.put(2, "2");
test.put(3, "3");
s = "1";
for (Integer i : test.keySet())
System.out.println("Key: " + i + ", Value: " + test.get(i));
}
}
}
The output is:
Key: 1, Value: String
Key: 2, Value: 2
Key: 3, Value: 3
Whats wrong here? I changed the value of String s right before Iterating the HashMap and it still shows the old value. That shows to me that HashMap DOES NOT work with object reference?
Where am I wrong in here?
Thanks for your time.
EDIT:
Tried with a test Object and the results are even more confusing since it seems like it WORKS for reference but not for Immutable objects as our fellow mate said:
class Test
{
private final static HashMap<Integer, TestObject> test = new HashMap<>();
public static void main(String[] args)
{
TestObject to = new TestObject();
test.put(1, to);
test.put(2, new TestObject());
test.put(3, new TestObject());
to.setValue(16);
for (Integer i : test.keySet())
System.out.println("Key: " + i + ", Value: " + test.get(i).getValue());
}
public static class TestObject
{
private int value;
public void setValue(int val)
{
value = val;
}
public int getValue()
{
return value;
}
}
}
this prints
Key: 1, Value: 16
Key: 2, Value: 0
Key: 3, Value: 0
I changed the value of String s
Yes, you changed the value of s
. That's all you changed. The map still contains the previous value of the variable. You haven't changed the meaning of that value.
We can simplify your example to just plain string variables:
String x = "hello";
String y = x;
x = "goodbye";
System.out.println(y); // "hello"
The assignment (y = x
) just copies the current value of x
into y
. That value is a reference, but it doesn't "know" where it came from - its only relation to the variable x
is that it happened to be the value of x
at the time of the assignment. When you later change the value of x
, that doesn't change the value of y
.
The exact same thing happens in Map.put
- the current value of the variable is used as the key. Changing the variable's value later doesn't affect the content of the map.
About mutability
None of the statements above depend on the mutability of the type in question. For example, you can see the exact same behaviour with StringBuilder
:
StringBuilder x = new StringBuilder("hello");
StringBuilder y = x;
x = new StringBuilder("goodbye");
System.out.println(y); // "hello"
You'll only see a change in behaviour if you change your code more drastically:
StringBuilder x = new StringBuilder("hello");
StringBuilder y = x;
x.append(" world");
System.out.println(y); // "hello world"
Compare these statements:
// First version
x = new StringBuilder("goodbye");
// Second version
x.append(" world");
The first version changes the value of x
. After the assignment, x
has a different value: a reference which refers to a different object. It's like moving to a different house: my home address is not the same as it was.
The second version does not change the value of x
. It changes the content of the object that the value of x
refers to. That's like painting the front door of my house: the address is still the same (it refers to the same house), it's just that some aspect of that house has changed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With