Custom equals / hash when inserting a key (Guava Cache)

I just have to override the way the cache selects the correct key, since some fields (for example, timestamp, message identifier, etc.) should not be taken into account when retrieving the key. I cannot change the actual hash function of the key object because it is already being used for recognition in my code.
Is this possible with Guava Caches? And with a workaround?

This is my configuration:

CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).recordStats(). expireAfterWrite(DEFAULT_AGE, TimeUnit.DAYS).build( new CacheLoader<Request, Response>() { @Override public Response load(Request request) { return request.getResponse(); } }); 

And this is my hash function (used somewhere else in my code):

 public int hashCode() { final int prime = 31; int result = 1; result = prime * result + code; result = prime * result + messageID; // <= **this one shouldn't evaluated** result = prime * result + Arrays.hashCode(payload); result = prime * result + (int) (timestamp ^ timestamp >>> 32); // <= **this one shouldn't evaluated** result = prime * result + (type == null ? 0 : type.hashCode()); result = prime * result + version; return result; } 

Btw, is it a cache that uses its own implementation of the hash function (for example, through introspection) or does it use it by default?

** EDIT: **
As indicated in the answers, the best way to achieve this result is a wrapper class.
My solution :

 /** * Nested class to store a request as a key in the cache. It is needed to * normalize the variable fields of the normal requests. */ private static final class CachedRequest extends Request { private static CachedRequest fromRequest(Request request) { // set only the fields that cannot change between two same requests // ... } @Override public int hashCode() { HashFunction hashFunction = Hashing.md5(); HashCode hashCode; // ... return hashCode.asInt(); } @Override public boolean equals(Object obj) { // coherent with hashCode() // ... } } 
+7
source share
3 answers

You can simply wrap Request objects in CachedRequest objects, where CachedRequest will implement hashCode() and equals() based on the desired fields and provide access to the wrapped Request .

+13
source

If you cannot change the hash function (I still don’t understand why), then you need to use the wrapper key for your cache, for example:

 public class RequestKey { private final Request _req; public int hashCode() { // use appropriate Request fields here } public boolean equals(Object o) { return ((this == o) || ((o != null) && (getClass() == o.getClass()) && _req.equals(((RequestKey)o)._req))); } } 
+1
source

I am sure this is not possible with Guava. There are some legitimate uses of user equivalence, but they say they are too rare to handle CacheBuilder and MapMaker . 1 There is even com.google.common.base.Equivalence , but it is used only internally (see also here and here ).

You need to make your own key from the fields that you want to use for the search, or wrap your Request in another object that defines equals and hashCode way you want.

1 The only case where a value other than the standard equals / hashCode , with weakKeys ( softKeys no longer exists), and then it == / System.identityHashCode combo. In no case can you freely choose equivalence.

+1
source

All Articles