3

New to Caffeine and I'm clearly missing something super fundamental. All the basic usage examples I see look like this:

LoadingCache<String,Fizzbuzz> fizzbuzzes = Caffeine.newBuilder()
    .maximumSize(100)
    .expireAfterWrite(10, TimeUnit.DAYS)
    .build(k -> fetchFizzbuzzes());

What I'm struggling with is the role that the fetchFizzbuzzes() function plays:

  • Is it used to populate the initial cache?
  • Is it used as some sort of fallback in case a key doesn't exist in the cache?
  • Something else?
hotmeatballsoup
  • 385
  • 6
  • 58
  • 136

1 Answers1

5

Actually this is the most important part of the builder. The function passed to the build(CacheLoader) method takes a key and computes the value for this key. This function is called if there is currently no value for this key in the cache. The computed value will be added to the cache afterwards. There is a build() method without arguments as well, which can be used if you want to manually check for elements to be present in the cache and add them manually as well.

Your example however doesn't make too much sense as the fetchFizzbuzzes() method has no arguments. That is - without side effects - it will probably return the same value for all keys k.

Take the examples below:

LoadingCache<String,Fizzbuzz> fizzbuzzes = Caffeine.newBuilder()
    .maximumSize(100)
    .expireAfterWrite(10, TimeUnit.DAYS)
    .build(key -> fetchFizzbuzzes(key));
fizzbuzzes.get("myKey"); // will automatically invoke fetchFizzbuzzes with 'myKey' as argument
fizzbuzzes.get("myKey"); // fetchFizzbuzzes won't be called as return value from previous call is added to the cache automatically


Cache<String, Fizzbuzz> fizzbuzzesManual = Caffeine.newBuilder()
     .maximumSize(100)
     .expireAfterWrite(10, TimeUnit.DAYS)
     .build();
fizzbuzzesManual.getIfPresent("myKey"); // will return null as no element for 'myKey' was added to the cache before

See the Caffeine wiki for additional details.

dpr
  • 10,591
  • 3
  • 41
  • 71
  • Thanks @dpr (+1) - is it possible to configure Caffeine in such a way that it just returns `null` if the key isn't in the cache? In other words, what if I don't have a good way (or don't want) to automatically fetch a value that isn't in the cache? Thanks again! – hotmeatballsoup Sep 08 '18 at 11:51
  • 1
    @hotmeatballsoup, see my edits. I think if the function passed to the build method returns `null`, this is interpreted as "value can't be computed" and the next time you try to get the value for the same key, the function will be called again, as the value is not stored in the cache. – dpr Sep 08 '18 at 12:06
  • Thanks for the edit @dpr but I actually get compilation errors when I try to use the no-arg `build()` method: `Incompatible types. Required LoadingCache but 'build' was inferred to Cache; no instance(s) of type variable(s) K1, V1 exist so that Cache conforms to LoadingCache`... any ideas there?! Thanks again so much! – hotmeatballsoup Sep 08 '18 at 12:07
  • 1
    @hotmeatballsoup, `build()` without arguments simply returns a `Cache` where `build(CacheLoader)` returns a `LoadingCache`. I fixed this in my answer as well. – dpr Sep 08 '18 at 12:09
  • Ahh, but then it seems if I have just a `Cache` that the `get()` method requires the cache loader? If so, what can I do to make `get()` return `null` if the Fizzbuzz doesn't exist in the cache? – hotmeatballsoup Sep 08 '18 at 12:11
  • 1
    Yes, just saw this, too. It's `getIfPresent(key)` for the non-loading `Cache`. – dpr Sep 08 '18 at 12:12