Map with expiry time in Java

Map in Java holds the value as key value pair. And it keeps the data there until the end of the application lifecycle. But sometimes a case could arise where you need to use the map with an expiry time, after which your particular entry will be removed. For that purpose here are a few examples from the various libraries of Java.

1. PassiveExpiringMap



Apache collection has a simple implementation for expiring hashmap which is PassiveExpiringMap. This uses the implementation of Map underneath. We just need to construct the object with a given expiry time after which an entry will be removed from the map.

Maven dependency:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>


Code snippet to show the usage. In this example we are setting the expiry time 1000 milliseconds, and adding entries to the map every 500 milliseconds.

    
    int expiryInMills = 1000;
    PassiveExpiringMap<String, Integer> map = new PassiveExpiringMap<>(expiryInMills);
    for (int i = 0; i < 10; i++) {
        map.put(String.valueOf(i), i);
        System.out.println(map.keySet());
        Thread.sleep(500);
    }


Pros:
  • Usage is very simple.
  • Comes with Apache collection which is sometimes available in the project.


Cons:
  • Not thread safe.
  • Removes expired values only when the get(), keySet(), or size() methods are called. More precisely, if we only do put() and do nothing, nothing will be removed from the map.


2. Guava cache



This is a Cache implementation that comes with the Guava. The main purpose of this is actually to serve as an in-memory cache. It has many features related to caching but among all two features are interesting (expire after write, and expire after access). For our needs we can use the expireAfterWrite() option which we can use to set the expiry time for an entry. Once that is set, any particular entry having that time will be removed.

Maven dependency:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>10.0.1</version>
</dependency>


Code snippet to show the usage. In this example we are using expiry time 1000 milliseconds and adding an entry to the cache after 500 milliseconds. We are setting the expiry time through expireAfterWrite().

    int expiryInMills = 1000;
    LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
            .expireAfterWrite(expiryInMills, TimeUnit.MILLISECONDS)
            .build(
                    new CacheLoader<String, Integer>() {
                        public Integer load(String key) {
                            return 1;
                        }
                    });
    for (int i = 0; i < 10; i++) {
        cache.put(String.valueOf(i), i);
        System.out.println(cache.asMap().keySet());
        Thread.sleep(500);
    }


Pros:
  • Implementation uses the concurrent hashmap underneath which is thread safe.
  • Comes with features for in-memory cache.


Cons:
  • Designed for Cache, and could be heavy if those features are not needed.
  • I think the latest version is still in beta. Otherwise none.


3. Caffeine Cache



Caffeine cache was introduced after being inspired by the Guava cache (but adding few features and improvements). For our purpose we don't need it. We only need the expiring entries from the map after the given time.

Maven dependency:

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.0.5</version>
</dependency>


Code snippet to show the usage. The usage is similar to the Guava cache.

    
    int expiryInMills = 1000;
    Cache<String, Integer> cache = Caffeine.newBuilder()
            .expireAfterWrite(expiryInMills, TimeUnit.MILLISECONDS)
            .build();

    for (int i = 0; i < 10; i++) {
        cache.put(String.valueOf(i), i);
        System.out.println(cache.asMap().keySet());
        Thread.sleep(500);
    }


Pros:
  • Similar to Guava cache. And comes with more features which Guava is missing.


Cons:
  • Designed for Cache, and could be heavy if those features are not needed.


Output



For all the above code snippet, the output is same, and it is

[0]
[1, 0]
[1, 2]
[3, 2]
[3, 4]
[5, 4]
[5, 6]
[7, 6]
[7, 8]
[8, 9]


Comments