简体   繁体   中英

HashMap with only most recent entries

I recently had an interview where the interviewer asked me to create a HashMap that has a maximum of 7 key/value pairs. If an 8th key/value pair is added, the first key/value pair should be removed and the eighth inserted to replace it, etc.

What's a good strategy for solving this problem?

The Java standard libraries contains a type called LinkedHashMap that does more or less what you're hoping to do here. It's like a regular HashMap except that it keeps track of the order in which elements were inserted. If you define a subclass and override the removeEldestEntry protected method, then the LinkedHashMap will automagically evict old elements and replace them with new ones on whatever schedule you'd like.

On the other hand, if you'd like to build something like this on your own, you're probably looking for something like a hash table that has a doubly-linked-list threaded through the elements. Whenever you insert an element, you append it to the linked list, and then, if there are too many elements, you remove the first element. I'll leave the details of how to do deletions, etc. up to you.

That being said, the above strategies are best-suited for fairly large maps (say, a hundred key/value pairs or more). If you only need to store seven key/value pairs, then it's almost certainly faster to just throw everything in an unsorted array and iterate over the elements to find the one you're looking for by just checking each. :-)

And finally, fun fact: what you're designing is sometimes called an LRU cache . These are used extensively in hardware and software.

Make a data structure using LinkedHashMap and override removeEldestEntry ie something like this:

import java.util.LinkedHashMap;

class CustomHashMap extends LinkedHashMap<Integer, Integer> {
    private int capacity;

    public CustomHashMap(int capacity) {
        super(capacity, 0.75F, true);
        this.capacity = capacity;
    }

    public int get(int key) {
        return super.getOrDefault(key, -1);
    }

    public void put(int key, int value) {
        super.put(key, value);
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
        return size() > capacity; 
    }
}

Alternatively, if you are not allowed to use standard libraries or you are using a language that does not have an ordered dictionary structure like Java/Python you can use a Hashtable + and a DoubleEndedLinkedList that you can define yourself and achieve the same thing or use a Deque :

  • Time complexity: O(1) for both put and get.
  • Space complexity: O(capacity) .

Although you have to write a lot more code.


Generic version as per @Holger 's request :

import java.util.LinkedHashMap;
import java.util.Map;

class CustomHashMap<K, V> extends LinkedHashMap<K, V> {
    private int capacity;

    public CustomHashMap(int capacity) {
        super(capacity, 0.75F, true);
        this.capacity = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > capacity;
    }
}

Example Usage:

class Main {
    public static void main(String[] args) {
        CustomHashMap map = new CustomHashMap(3);
        map.put(1, null);
        map.put(2, null);
        map.put(3, null);
        map.put(4, null);
        System.out.println(map.keySet());
    }
}

Output:

[2, 3, 4]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM