Given an immutable object, it sometimes makes sense to cache its hashcode. Below is an example.
In the example, I realize that caching is more expensive than just recalculating the hashCode.
public class ImmutableObject{
final int immutableField1;
final String immutableField2;
//volatile? transient? WeakReference?
private Integer cachedHashCode = null;
@Override
public int hashCode() {
Integer ret=cachedHashCode;
if(ret == null) {
ret = immutableField1;
ret = 31 * ret + immutableField2.hashCode();
}
cachedHashCode = ret;
return ret;
}
// constructor, equals, other methods...
}
What modifiers does cachedHashCode
need?
- Volatile: Effective Java recommends using the volatile modifier here (how caching hashcode works in Java as suggested by Joshua Bloch in effective java?). As the class is immutable, under what conditions would non-strict execution ordering be dangerous? Is it solely to prevent redundant calculation of the hashCode?
- Transient: If the hashcode is derived it is almost certainly cheaper to recalculate it than to serialize/deserialize it. Under what conditions would you want to serialize a hashcode?
- WeakReference: If the class only has a couple fields, yet hashCode caching is still (somehow) worthwhile, the cached hashcode may add significantly to the memory footprint of each object. Should the cache then be a WeakReference? Will a WeakReference always take up at least as much space as the cached int?