user3789587
user3789587

Reputation: 105

HashMap Object reference confusion

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

Upvotes: 9

Views: 16930

Answers (4)

Ankit Katiyar
Ankit Katiyar

Reputation: 3001

Their is nothing wrong with the HashMap. You are mis-understanding the concept of String object.

String is immutable. That means how many time you make changes in string object it will create a new object and provide the reference to variable.

Just test this small Code

String s="String";
System.out.println("Old-"+s.hashCode());
s="New String";
System.out.println("New-"+s.hashCode());

Output

Old--1808118735
New-1745736401

Here you can see as you made change to String variable it's hascode is changed that means a new object created in String Pool and new reference to the variable.

I your case

HashMap<Integer, String> test=new HashMap<Integer, String>();
String s = "String";
System.out.println("Adding with -"+s.hashCode());
test.put(1, s);
test.put(2, "2");
test.put(3, "3");
s = "1";
System.out.println("Modified s-"+s.hashCode());
for (Integer i : test.keySet())
    System.out.println("Key: " + i+ ", Value: " + test.get(i)+"  "+test.get(i).hashCode());
}

Write it like this and see the magic output.

Adding with --1808118735
Modified s-49
Key: 1, Value: String  -1808118735
Key: 2, Value: 2  50
Key: 3, Value: 3  51

HashMap still contains the old string reference.

Upvotes: 8

Jon Skeet
Jon Skeet

Reputation: 1501103

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.

Upvotes: 13

Saif
Saif

Reputation: 7042

Let me give u an example: Here the real objects are like any place say Home and reference are their address. Now you are making a list of addresses it can be HashMap or List of anything.

Assume you have a piece of paper and address of Home1 written on it. Now you give this paper to you friend to make a list and he copy this address in his list. Now you throw you parer and pick another paper which contain address of Home2. Now if you deliver something it will go to Home2 and if you friend deliver something according to the list it will go to Home1.

That's why when you change the value of s

 s = "1";

it change the value of s but doesn't change the value of reference inside the list.

**Actually you are not changing the value of the object that pointed by s you are telling s to point another object.**

Upvotes: 2

Abhishek Mishra
Abhishek Mishra

Reputation: 639

As per your code S reference pointing to object "String". And hashMap key i.e. "1" is also pointing to object"String" once test.put(1, s); get executed,now you change s pointing object ,means after you change the value of s to 1 ,now s is pointing to object"1" and key "1" of hashmap is still pointing to object "String".

Upvotes: 0

Related Questions