I have the following piece of code from effective java by Joshua Bloch (Item 9, chapter 3, page 49)
If a class is immutable and the cost of computing the hash code is significant, you might consider caching the hash code in the object rather than recalculating it each time it is requested. If you believe that most objects of this type will be used as hash keys, then you should calculate the hash code when the instance is created. Otherwise, you might choose to lazily initialize it the first time hashCode is invoked (Item 71). It is not clear that our PhoneNumber class merits this treatment, but just to show you how it’s done:
// Lazily initialized, cached hashCode
private volatile int hashCode; // (See Item 71)
@Override public int hashCode() {
int result = hashCode;
if (result == 0) {
result = 17;
result = 31 * result + areaCode;
result = 31 * result + prefix;
result = 31 * result + lineNumber;
hashCode = result;
}
return result;
}
my question is how the caching (remembering the hashCode) works here. The very first time, hashCode()
method is called, there is no hashCode
to assign it to result. a brief explanation on how this caching works will be great.
Thanks
Simply put, hashCode() returns an integer value, generated by a hashing algorithm. Objects that are equal (according to their equals()) must return the same hash code. Different objects do not need to return different hash codes.
Java's own String class is a good example where the hashCode is only calculated once, and then cached. Since EqualsVerifier relies on reflection to change the content of fields and then calling equals and hashCode to see if they changed, it can't deal with cached hashCodes very well.
hashCode in Java is a function that returns the hashcode value of an object on calling. It returns an integer or a 4 bytes value which is generated by the hashing algorithm. The process of assigning a unique value to an object or attribute using an algorithm, which enables quicker access, is known as hashing.
Simple. Read my embedded comments below...
private volatile int hashCode;
//You keep a member field on the class, which represents the cached hashCode value
@Override public int hashCode() {
int result = hashCode;
//if result == 0, the hashCode has not been computed yet, so compute it
if (result == 0) {
result = 17;
result = 31 * result + areaCode;
result = 31 * result + prefix;
result = 31 * result + lineNumber;
//remember the value you computed in the hashCode member field
hashCode = result;
}
// when you return result, you've either just come from the body of the above
// if statement, in which case you JUST calculated the value -- or -- you've
// skipped the if statement in which case you've calculated it in a prior
// invocation of hashCode, and you're returning the cached value.
return result;
}
The hashCode
variable in an instance variable, and it's not initialized explicitly, so Java intializes it to 0
(JLS Section 4.12.5). The comparison result == 0
is in effect a check to see if result
has been assigned a presumably non-zero hash code. If it hasn't been assigned yet, then it performs the calculation, else it just returns the previously computed hash code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With