Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

hash code for enum and long field combined

 
B Nirvan
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have an object whose primary identity consists of a combination of an Enum type and a long. What hashcode generation logic should I use for efficient fetching of the object from maps or some other functioning.

regards,
Nirvan
 
Rob Spoor
Sheriff
Pie
Posts: 20751
68
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The topic of creating efficient hashCode implementations warrants at least one book of its own; it's a very advanced topic.

What I usually do is something like this:
The prime is mostly 31, but I can't remember why. Probably because I've seen it being used a lot; even String uses it.
 
Campbell Ritchie
Sheriff
Posts: 51436
87
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How about

. . . myEnum.hashCode() * 31 + (int)((myLong >> 0x20) ^ myLong) . . . ?

Assuming you only have those two fields. I can't remember whether ^ has a higher precedence than >> or vice versa.
 
Campbell Ritchie
Sheriff
Posts: 51436
87
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It says in a book I have read, possibly Bruce Eckel's Thinking in Java™ 4/e, that i * 31 can be optimised to (i << 5) - i which is faster than multiplication.
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
NetBeans will generate a hashCode() for you, based on the fields you want to use, and it uses a similar approach. I just tried it out and got this:

 
Rob Spoor
Sheriff
Pie
Posts: 20751
68
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Almost the same approach: take the previous hash code, multiply by a prime number, and add a new part to it. The only difference is that my initial value is 0 instead of a prime number (7). 1 is also a sometimes used initial value.

The usual "rules" for calculating hash code parts:
- objects: (object == null ? 0 : object.hashCode())
- byte, char, short, int: the value itself
- float: Float.floatToIntBits(value)
- long: (int)(value ^ (value >>> 32)) (i.e. what Matthew already posted)
- double: Double.doubleToLongBits(value) to convert to long, then the long to hashCode computation
- boolean: use Boolean.valueOf(value).hashCode(). This (currently) returns 1231 for true, 1237 for false. Because Boolean.valueOf(boolean) always returns one of the two static final fields it won't add any memory usage.
 
Stephan van Hulst
Bartender
Pie
Posts: 6503
83
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:How about

. . . myEnum.hashCode() * 31 + (int)((myLong >> 0x20) ^ myLong) . . . ?

Assuming you only have those two fields. I can't remember whether ^ has a higher precedence than >> or vice versa.


Unary > Arithmetic > Comparison > Bitwise > Logical > Ternary > Assignment
These are broad categories I have memorized in order to remember the precedence.
Note that bitwise shifts are considered arithmetic, so they trump xor operations.
 
Campbell Ritchie
Sheriff
Posts: 51436
87
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are right; >> has a higher precedence than ^ so one of my pairs of () is redundant.
 
B Nirvan
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Whew,
It seems I will have to read some book before I get to fully understand all your replies. Meanwhile, I will follow Matthew's suggestion and let the netbeans produce the hashCode and equals. Here is the code generated by Netbeans. In the code the phoneType is the enum and donorId is long. I hope this is efficient.


Thanks for the replies.

regards,
Nirvan.
 
Rob Spoor
Sheriff
Pie
Posts: 20751
68
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wait what? That can't be right. donor is definitely not a long; it's being used as an Object (comparing against null, calling methods on it, etc). Is it perhaps a Long?
 
B Nirvan
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Rob,
Sorry for being late to respond. Donor is definitely an object as you guessed, but it has a long id as donorId. The hashcode for it is also generated by netbeans. So in short the Phone Entity has effectively an Identity that is composed of PhoneType and DonorId (mapped as Donor in hibernate). The hashcode generation logic for Phone entity refers to the hashcode of Donor entity. So I think this must work correctly.

thanks and regards,
Nirvan
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic