Inheriting LinkedHashMap to Implement Custom HashMap Setting Conditions to Trigger Delete eldest Elements

Analysis of LinkedHashMap

LinkedHashMap is a subclass inheriting HashMap. In addition to the method containing HashMap, it also provides the removeEldestEntry method, which is implemented in source code.

protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
    return false;
}

This method doesn't seem to work. Don't jump to conclusions so quickly. Let's see where the method was called first.
Upper source code:

void addEntry(int hash, K key, V value, int bucketIndex) {
    super.addEntry(hash, key, value, bucketIndex);

    // Remove eldest entry if instructed
    Entry<K,V> eldest = header.after;
    if (removeEldestEntry(eldest)) {
        removeEntryForKey(eldest.key);
    }
}

Seeing this call, it seems that you can see the function of this method. When removeEldestEntry returns true, you execute removeEntry ForKey to delete the entry of eldest (LRU is Least Current Used, the Least Recently Used), but the implementation of removeEldestEntry method in the previous source code always returns false, that is, removeEntry ForKey method will never execute.
Let's see where the addEntry method is invoked:

public V put(K key, V value) {
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

As you can see, it's called in the put method, and the logic is analyzed again, as if removeEldestEntry is ready to play its role.
Guess: When the set puts key-value, the removeEldestEntry method is executed to check the condition (e.g. the set is full), and then return true, delete the eldest element, and release the space.

Inheriting LinkedHashMap to Delete eldest Elements under Specific Conditions

Define a class to inherit LinkedHashMap

public class LRUHashMap<K, V> extends LinkedHashMap<K, V>{


        private final int MAX_CACHE_SIZE;

        public BaseLRUCache(int cacheSize) {
            super(cacheSize, 0.75f, true);
            MAX_CACHE_SIZE = cacheSize;
        }

        @Override
        protected boolean removeEldestEntry(Map.Entry eldest) {
            return size() > MAX_CACHE_SIZE;
        }

        public abstract void removeKey(String key);

}

LRUHashMap is a custom inheritance class of LinkedHashMap, which not only owns the method of LinkedHashMap, but also rewrites the removeEldestEntry method. The meaning of this method is to return true when the sub-elements of LRUHashMap set reach a certain threshold MAX_CACHE_SIZE.

Then review the previous addEntry method

if (removeEldestEntry(eldest)) {
    removeEntryForKey(eldest.key);
}

If this condition is satisfied, the eldest element is deleted.

For example, when local caching is implemented, if the content of caching reaches a certain threshold, the least recently used elements can be deleted and the space released for new elements to use.

But review the addEntry method:

Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) {
    removeEntryForKey(eldest.key);
}

The eldest object always seems to be the first element (non-header), so the best implementation of LRUHashMap should be to rewrite the addEntry method and add some (LRU, etc.) algorithms to select the object with the lowest weight as the eldest object to be remove d.

Added by TMX on Thu, 13 Jun 2019 00:56:50 +0300