Win a copy of Design for the Mind this week in the Design forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Searching in a Map

 
ven jovovich
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi everyone,
In the following code I think the second and last print statements should NOT print null, but unfortunately they do . Where am I going wrong?


Thanks.
 
Nikhil Sagar
Ranch Hand
Posts: 216
Java Linux Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome ven jovovich into the great world of java lovers,
You are getting null just because In this line.


when you are puting this key value in the HashMap it will go into the....say a Bucket with number 4, i said bucket number 4 because in your hashcode generating algorithm you will get 4 as a hashcode for this (d2) object.
Ok, But after that you changed the name inside the d2 Object, But it doesn't means that the bucket will automatically updates that means the bucket is still no 4.

Now when you try you search for this with key ,



it will generate again a hashcode for this particular Object and Unfortunetly it will be 3, So, Where to search for the corresponding value.
Yes, Of-course it will search for the corresponding value in the bucket no 3.
Thats why it will return you null because there is nothing in the bucket no 3 corresponding to this key.
 
Javin Paul
Ranch Hand
Posts: 295
Eclipse IDE Firefox Browser Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is one of the reason that HashMap keys should be immutable, because you can not change immutable object once created so calling to hashCode() will always return same hashcode.
 
Nikhil Sagar
Ranch Hand
Posts: 216
Java Linux Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Javin Paul wrote:This is one of the reason that HashMap keys should be immutable, because you can not change immutable object once created so calling to hashCode() will always return same hashcode.


Agree, But it is not always possible So,
I think If you make name field of Dog class private you can fix the problem for sure.
And there will be no fun if you always follow the conventions.

 
Javin Paul
Ranch Hand
Posts: 295
Eclipse IDE Firefox Browser Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Nikhil, I can bet you production issues will not be fun , better to be safe than sorry.
 
Nikhil Sagar
Ranch Hand
Posts: 216
Java Linux Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Javin Paul wrote:Hi Nikhil, I can bet you production issues will not be fun , better to be safe than sorry.


You are Absolutely correct Jevin but , Sometimes during production by applying new things you can get better results than convention says.
And Friend, I and almost all java folks around world always use their own defined class' Objects as a key. I know it is good in the learning phase but you will not get much more by using that.
For example What if you want a Dog as a key and owner of that Dog as value.
 
Javin Paul
Ranch Hand
Posts: 295
Eclipse IDE Firefox Browser Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikhil Sagar wrote:
Javin Paul wrote:Hi Nikhil, I can bet you production issues will not be fun , better to be safe than sorry.


You are Absolutely correct Jevin but , Sometimes during production by applying new things you can get better results than convention says.
And Friend, I and almost all java folks around world always use their own defined class' Objects as a key. I know it is good in the learning phase but you will not get much more by using that.
For example What if you want a Dog as a key and owner of that Dog as value.



Hi Nikhil,
I agree with you on learning part, learning by experience is good thing but you also need Guidance to learn right things and avoid misconception.
By the way If you want to use Dog as key than you should make it Immutable to avoid such issues. Value classes are actually good candidate to be Immutable.
 
Nikhil Sagar
Ranch Hand
Posts: 216
Java Linux Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But i don't think that there is any need of make a whole class nearly perfectly immutable, just by making the key field private you used in equals() and (or) hashcode() you can achieve all desired results.
Am i Wrong Jevin ??
 
ven jovovich
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks. Solved.
 
Rob Spoor
Sheriff
Pie
Posts: 20511
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Although it isn't the cause of the error this time, you shouldn't use == for comparing Strings. You should always use the equals method.
 
Javin Paul
Ranch Hand
Posts: 295
Eclipse IDE Firefox Browser Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikhil Sagar wrote:But i don't think that there is any need of make a whole class nearly perfectly immutable, just by making the key field private you used in equals() and (or) hashcode() you can achieve all desired results.
Am i Wrong Jevin ??


Yes you are fine, Until your code guarantee that hashCode will always return same value. by not making field final and just making it private can still cause issue if any method unintentionally modify it. By making it final , compiler will ensure it for you.
 
ven jovovich
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Spoor wrote:Although it isn't the cause of the error this time, you shouldn't use == for comparing Strings. You should always use the equals method.


Could you please explain why you think it's better to do that? In String, equals() is defined as:



I dont see the advantage of using "equals()" to compare Strings.

Thanks.
 
Rob Spoor
Sheriff
Pie
Posts: 20511
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's only the start, as a shortcut to prevent having to check the entire String if you're checking the same object. If you check the entire method you'll see that if that if-statement is not executed, the String contents are checked.
 
ven jovovich
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot Rob. Still wondering how I missed the second if block...


...but then again, if two String objects are "==" they are "equal" (equals() returns true) and if they are not "==", equals() should return false since same strings (lowercase s) are always "=="... the String pool comes into play and all...
So is that second if block really necessary?

Thanks.
 
Nikhil Sagar
Ranch Hand
Posts: 216
Java Linux Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
ven jovovich wrote:Thanks a lot Rob. Still wondering how I missed the second if block...


...but then again, if two String objects are "==" they are "equal" (equals() returns true) and if they are not "==", equals() should return false since same strings (lowercase s) are always "=="... the String pool comes into play and all...
So is that second if block really necessary?

Thanks.


Yes Ven that is absolutely necessary because there are two types by which you can make a String Object.
you already know first but what if you make two String Objects by new keyword and same arguments.
For example,

In that case '==' will never return true that means first if condition fails.
But they are meaningfully equal.
So, now the Second if condition comes into play.
Just to make it more understandable to you i am posting a code, try to predict its output and reasons behind it.
 
Nikhil Sagar
Ranch Hand
Posts: 216
Java Linux Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Javin Paul wrote:
Nikhil Sagar wrote:But i don't think that there is any need of make a whole class nearly perfectly immutable, just by making the key field private you used in equals() and (or) hashcode() you can achieve all desired results.
Am i Wrong Jevin ??


Yes you are fine, Until your code guarantee that hashCode will always return same value. by not making field final and just making it private can still cause issue if any method unintentionally modify it. By making it final , compiler will ensure it for you.


But what if i need to change the value inside that field just because Now my existing Dog (name was Tiger) have a new name (new name is Viper).
i mean without affecting the hashcode means, hashcode for the new value is still same as the old one but i just want to update the new name.
How can i do that ??
 
Winston Gutkowski
Bartender
Pie
Posts: 10243
58
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikhil Sagar wrote:But what if i need to change the value inside that field just because Now my existing Dog (name was Tiger) have a new name (new name is Viper).
i mean without affecting the hashcode means, hashcode for the new value is still same as the old one but i just want to update the new name. How can i do that ??

Simply put: if name is part of the identification of a Dog (ie. Dog.equals(Dog) contains any comparison of names), you CAN'T.

equals() and hashCode() must always be in sync, so if you change any field in Dog that is referenced in equals(), you must also change the hashCode() calculation.

Winston
 
Rob Spoor
Sheriff
Pie
Posts: 20511
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, it's of course possible to let hashCode use less fields than equals. Let's say you have a class with an ID and a name field. equals checks both ID and name. If you let hashCode use only ID that's just fine.

You can even choose to use no fields at all, but that means hashCode should return a constant which means that a HashMap essentially turns into a LinkedList, as there will be only one bucket.
 
ven jovovich
Ranch Hand
Posts: 33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot Nikhil.
 
Winston Gutkowski
Bartender
Pie
Posts: 10243
58
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Spoor wrote:Well, it's of course possible to let hashCode use less fields than equals. Let's say you have a class with an ID and a name field. equals checks both ID and name. If you let hashCode use only ID that's just fine.

Seems an odd way to go about things if ID is already a unique identifier. Surely better to have a separate Comparator which compares by name, no?

@Nikhil: The fact is that you only need hashCode() if you plan on putting your object into a hashed collection; however, since they are extremely useful, the normal rule of thumb is to always implement equals() and hashCode() together, and to always keep them in sync (ie, have them work with the same fields).

Winston
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic