aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Getting Wrong Output When Trying to Write a Program on HashMap Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Java 8 in Action this week in the Java 8 forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Getting Wrong Output When Trying to Write a Program on HashMap" Watch "Getting Wrong Output When Trying to Write a Program on HashMap" New topic
Author

Getting Wrong Output When Trying to Write a Program on HashMap

Sidharth Khattri
Ranch Hand

Joined: Sep 16, 2013
Posts: 121

So, I was studying this topic: HashMap, when I decided to write a code for practice. It's almost like the one mentioned in K&B book, but I'm not getting the expected output. This is the code that I've written:



Getting Output:
dog key
null

Expected Output:
dog key
true

The hashCode() should find the bucket of size 6 and equals() should return true, why is the output null and not true?

But now, when I make a small change in the code(added a new line) I'm getting the correct Output. Why is it so?

Changed code:



Getting Output:
dog key
new dog key

Expected output:
dog key
new dog key

What difference does it make when I added that extra line in the code? Why is the code behaving this way?

OCPJP 6 - 96%
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4244
    
    7

Hi Sidharth. Welcome to the Ranch!

I'm not certain this is the only cause, but I can see at least one thing you're doing wrong:
Never use == to compare Strings. Your equals() method doesn't work correctly. Try changing that and see is that changes the behaviour.

Oh, by the way: thanks for using code tags to display your code, but can you indent it consistently as well in future? It makes it much easier to read. Thanks!
Sidharth Khattri
Ranch Hand

Joined: Sep 16, 2013
Posts: 121

Matthew Brown wrote:Hi Sidharth. Welcome to the Ranch!

I'm not certain this is the only cause, but I can see at least one thing you're doing wrong:
Never use == to compare Strings. Your equals() method doesn't work correctly. Try changing that and see is that changes the behaviour.

Oh, by the way: thanks for using code tags to display your code, but can you indent it consistently as well in future? It makes it much easier to read. Thanks!


In K&B(SCJP Sun Certified Programmer for Java 6-0071591060) at Page Number 583 they have used == to compare strings:

That's why I used it. Although I was not sure as I thought string should be compared using equals() or equalsIgonreCase(). Nevertheless, it gives the same output, i.e, null.

I still don't get it.
And btw, thanks for quick reply and I'll make sure to indent it properly in future.
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4244
    
    7

OK, I've had a closer look, and I can see the problem now.

It's a bad idea to use mutable objects as keys in maps, and it's a bad idea to have equals() or hashCode() depend on mutable fields. What you've got there is a good demonstration why. The problem is this line:

When the original dog put in the map, the name is "tank". Which means the hash code is 4.

Then you change the name of the key to "clover". Now its hash code is 6. That means it isn't in the bucket of the HashMap that it ought to be in. So when you try to lookup the value, using an equal key, the HashMap looks in the 6 bucket and says "nothing there", and never finds the dog that's still in the 4 bucket.

Adding your extra line means that you do have the key in the right bucket - although now you'll have the same key in there twice, which isn't good. The other way you could get different behaviour is if you swap "clover" in both places for a four letter word. Now the key is still in the bucket it should be.

(Regardless of what K&B did in that example, you definitely should use equals(). It doesn't matter in this specific example because of the string pool and the fact that you are only using string literals that will all be put in the string pool).
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18136
    
  39

Sidharth Khattri wrote:
In K&B(SCJP Sun Certified Programmer for Java 6-0071591060) at Page Number 583 they have used == to compare strings:

That's why I used it. Although I was not sure as I thought string should be compared using equals() or equalsIgonreCase(). Nevertheless, it gives the same output, i.e, null.

I still don't get it.
And btw, thanks for quick reply and I'll make sure to indent it properly in future.



Whether a string "should be compared using equals() or equalsIgonreCase()" is dependent on your program design. Do you want your program to consider upper case and lower case letters to be the same?

And as for your issue... the key of a hashmap should not change. When you changed the name of the dog from "tank" to "dog key", you changed the hashcode after an instance has been inserted. This means that it is very likely that the key is in the wrong bucket, and likely that the hashmap has been corrupted. Don't do that. Don't change key instances that has already been placed into the hashmap.

Henry
Sidharth Khattri
Ranch Hand

Joined: Sep 16, 2013
Posts: 121

Thanks @Matthew Brown for your insightful explanation.
Can you please elucidate this line:
"Adding your extra line means that you do have the key in the right bucket - although now you'll have the same key in there twice, which isn't good. The other way you could get different behaviour is if you swap "clover" in both places for a four letter word. Now the key is still in the bucket it should be. "

At first, the key was "tank" having hashCode of 4, then I changed the key to clover having hashCode 6. Will "tank" key's bucket still exist? Or it's just that the "clover" key's bucket exists' now? How will there be same key twice?

I comprehended this from your explanation:
The value "dog key" is still in bucket with hashcode 4, but the key is changed to "clover" which created a new bucket with hashcode 6 and this bucket is empty. So when I try to get any value using the key "clover", it'll return null as there isn't anything in bucket with hashcode 6 which the key "clover" refers to.
And this line:

adds a new value "new dog key" to the bucket with hashcode 6, so when in the next line I try to get the value through the key "clover" I get an output "new dog key" because I added this new value to the bucket with hashcode 6.
Am I right?

@Henry Wong
And as for your issue... the key of a hashmap should not change. When you changed the name of the dog from "tank" to "dog key", you changed the hashcode after an instance has been inserted. This means that it is very likely that the key is in the wrong bucket, and likely that the hashmap has been corrupted. Don't do that. Don't change key instances that has already been placed into the hashmap.


I think I changed the name of dog from "tank' to "clover". I hope I'm not wrong. Still learning.
I changed the key that changed the hashcode, but which instance was inserted where? I don't get it
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18136
    
  39

Sidharth Khattri wrote:Thanks @Matthew Brown for your insightful explanation.
Can you please elucidate this line:



To emphasize, what your code does is corrupt the hashmap... this means that it may still work (according to JavaDoc), this means that it may not, and of course, this means that any explanation may be moot. It may be true for one JVM but not another. It may be true for one platform, but not another. etc.

So... understand that any explanation given here is only currently true, and only for the version used by the person explaining. The discussion will be regarding implementation detail, and for a corrupted condition.

Anyway...
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18136
    
  39

Sidharth Khattri wrote:
I comprehended this from your explanation:
The value "dog key" is still in bucket with hashcode 4, but the key is changed to "clover" which created a new bucket with hashcode 6 and this bucket is empty. So when I try to get any value using the key "clover", it'll return null as there isn't anything in bucket with hashcode 6 which the key "clover" refers to.


No. The HashMap doesn't know that. When you changed the key's state, nothing else changes. The key is still in the same bucket, which of course, may or may not be the correct bucket. Also, duplicate detection has not be done, so it may also be a duplicate. So, it may return null, as you explained, or it may still work -- if by chance the implementation maps the two hashcodes to the same bucket.

Henry

Sidharth Khattri
Ranch Hand

Joined: Sep 16, 2013
Posts: 121

I found the entire explanation for hashmap here:
http://howtodoinjava.com/2012/10/09/how-hashmap-works-in-java/

As a matter of fact, I think I got it right. I don't know why nobody is willing to ratify it in a more lucid manner. Or maybe I am partially/completely wrong.

Thanks Henry Wong for your replies.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Getting Wrong Output When Trying to Write a Program on HashMap
 
Similar Threads
Hashmap doubt from K&B
Please explain HashMap?
Collection - Chap 7 (Maps) (Problem in Understanding an example in K&B SCJP 1.6)
equals() doesn't fail for 2 different strings of the same hashCode Pages 583, 584, 585 of SCJP6
doubt on hashCode