Search code examples
javagoogle-guava-cache

Why getAll method of Guava LoadingCache returns different types of ImmutableMap?


I have simple Guava LoadingCache use case where I pass list of key objects to getAll and implemented loadAll to get results when not available in cache.

The problem is When cache is empty,

  • Calling getAll for collection of records returns Map of type RegularImmutableMap.
  • And calling getAll for collection of single record returns Map of type SingletonImmutableBiMap.

This eventually leads to another problem. When I try to collect map.values() on it, RegularImmutableMap returns a type of ImmutableList and SingletonImmutableBiMap returns a type of ImmutableSet.

From user perspective is there any specific reason/advantage why getAll method returns different types of ImmutableMap?


Solution

  • Note this has nothing to do with Cache - the LocalCache implementation you're presumably using simply calls ImmutableMap.copyOf() before returning the collected results.

    So your underlying question is really why does ImmutableMap.of(K, V) return an ImmutableBiMap?

    This has been the behavior since 2012 and the short answer is because ImmutableBiMap extends ImmutableMap, therefore there's no need to have both a SingletonImmutableMap and SingletonImmutableBiMap implementation.

    As matoni has said, ImmutableMap.values() returns an ImmutableCollection, therefore you cannot rely on a particular implementation to return an ImmutableList or an ImmutableSet (or some other mysterious type that extends ImmutableCollection). Not only that, you cannot rely on the existing behavior staying this way! For a brief while (from February to June) ImmutableMap actually didn't use ImmutableBiMap.

    This means you should not expect ImmutableMap.values() to return an ImmutableList, and any code that does so is broken. If you need an ImmutableList from an ImmutableCollection use .asList() - for most immutable collections this can return a view in O(1) time and space.