Monday, February 27, 2012

How to pre-populate Guava CacheBuilder cache

I haven't blogged for a while now and this is my attempt at a fresh start. In the meanwhile I have started a new job in San Francisco leading the Android apps team at Betfair and it has been hectic. I will try to be more regular in my posts here as there are a lot of things I want to share.

In my current job we are using Guava CacheBuilder, its part of Guava Collections open source library for implementing LRU cache for some data in our Android app. But there is one deficiency in this, it does not allow us by default to prepopulate the cache. When an object is requested, CacheBuilder looks for it in its cache, if it can't find it, CacheBuilder fetches it, caches it and then returns it to the user. This wasn't what I needed as I needed to pre-populate the cache. Here is how I did it. First initialize the cache.

 Cache<Integer, NavigationNode> lruCache =   
     CacheBuilder  
     .newBuilder()  
     .concurrencyLevel(4)  
     .maximumSize(500)  
     .expireAfterWrite(3, TimeUnit.MINUTES)  
     .build(  
         new CacheLoader() {  
           @Override  
           public NavigationNode load(Integer nodeId)  
               throws Exception {  
             return null;  
           }  
         }  
      );  

Then this is how you pre-populate the cache:
 lruCache.asMap().putIfAbsent(id, navNode);  
lruCache.asMap() returns a view of the entries stored in the cache as a thread-safe map. And modifications to this map are same as modifiying the cache. So putIfAbsent() just puts the navNode object in cache, if it is not already in it. Now if we use this line in a for loop that makes it trivial to pre-populate the cache.