How do we decide on the best implementation of hashCode()
method for a collection (assuming that equals method has been overridden correctly) ?
相关问题
- Delete Messages from a Topic in Apache Kafka
- Jackson Deserialization not calling deserialize on
- How to maintain order of key-value in DataFrame sa
- StackExchange API - Deserialize Date in JSON Respo
- Difference between Types.INTEGER and Types.NULL in
I prefer using utility methods fromm Google Collections lib from class Objects that helps me to keep my code clean. Very often
equals
andhashcode
methods are made from IDE's template, so their are not clean to read.Here is another JDK 1.7+ approach demonstration with superclass logics accounted. I see it as pretty convinient with Object class hashCode() accounted, pure JDK dependency and no extra manual work. Please note
Objects.hash()
is null tolerant.I have not include any
equals()
implementation but in reality you will of course need it.If I understand your question correctly, you have a custom collection class (i.e. a new class that extends from the Collection interface) and you want to implement the hashCode() method.
If your collection class extends AbstractList, then you don't have to worry about it, there is already an implementation of equals() and hashCode() that works by iterating through all the objects and adding their hashCodes() together.
Now if what you want is the best way to calculate the hash code for a specific class, I normally use the ^ (bitwise exclusive or) operator to process all fields that I use in the equals method:
As you specifically asked for collections, I'd like to add an aspect that the other answers haven't mentioned yet: A HashMap doesn't expect their keys to change their hashcode once they are added to the collection. Would defeat the whole purpose...
The best implementation? That is a hard question because it depends on the usage pattern.
A for nearly all cases reasonable good implementation was proposed in Josh Bloch's Effective Java in Item 8 (second edition). The best thing is to look it up there because the author explains there why the approach is good.
A short version
Create a
int result
and assign a non-zero value.For every field
f
tested in theequals()
method, calculate a hash codec
by:boolean
: calculate(f ? 0 : 1)
;byte
,char
,short
orint
: calculate(int)f
;long
: calculate(int)(f ^ (f >>> 32))
;float
: calculateFloat.floatToIntBits(f)
;double
: calculateDouble.doubleToLongBits(f)
and handle the return value like every long value;hashCode()
method or 0 iff == null
;Combine the hash value
c
withresult
:Return
result
This should result in a proper distribution of hash values for most use situations.
Although this is linked to
Android
documentation (Wayback Machine) and My own code on Github, it will work for Java in general. My answer is an extension of dmeister's Answer with just code that is much easier to read and understand.EDIT
Typically, when you override
hashcode(...)
, you also want to overrideequals(...)
. So for those that will or has already implementedequals
, here is a good reference from my Github...