Search code examples
javahashequalsguava

Custom equals/hash when inserting key (Guava Cache)


Simply, I have to override the way in which the cache chooses the right key because some fields (e.g., timestamp, message id, etc.) shouldn't be considered when retrieving a key. I cannot modify the actual hash function of the key object because it is already used to recognize in my code.
Is it possibile 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 this kind of cache using its own implementation of hash function (e.g., through introspection) or is it using the default one?

** EDIT: **
As pointed out in the responses, 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()
            // ...
    }
}

Solution

  • You could simply wrap your Request objects into CachedRequest objects, where CachedRequest would implement hashCode() and equals() based on the desired fields, and provide access to the wrapped Request.