introduce

A cache class that holds strong references to cached objects. Whenever a cached value is used, it is placed at the top of the data container. When the cache is full, the cache value at the end of the data container is expelled.

Pay attention to the point

  • Override entryRemoved if your cache object needs to be shown freed
  • If the read cache misses and needs to generate an object return for the read, you need to override create. This way, the user can assume that the nightclub returns a value even if the cache misses.
  • By default, the size of the cache is the number of computed entries. You can do that by overwriting sizeOf and the size of the cache is the sum of the values of each entery.
  • LruCache does not allow null as a key or value. If return is null, there is no value corresponding to the key
  • The operation provided by LruCache is thread-safe.

reading

LinkedHashMap is the core data container for Lrucache, and Lrucache’s least recently used policy is also implemented naturally through LinedHashMap. We won’t talk about the storage of LinkedHashMap here, just the initialization of LurCache, the GET /put/remove operation.

Initialize the

public LruCache(int maxSize) {
        if (maxSize <= 0) {
            throw new IllegalArgumentException("maxSize <= 0"); } this.maxSize = maxSize; This. Map = new LinkedHashMap<K, V>(0, 0.75f,true);
    }
Copy the code

Just initialize the maxSize field and do nothing special.

get

Public final V get(K key) {// Verify that key cannot be nullif (key == null) {
            throw new NullPointerException("key == null"); } V mapValue; Synchronized (this) {mapValue = map.get(key);if(mapValue ! = null) { hitCount++;returnmapValue; } missCount++; } // Create a value if no match is made. If create is not overridden, return null // This method may have concurrent operations. If concurrency occurs, discard createValue V createdValue = create(key) forever;if (createdValue == null) {
            returnnull; Synchronized (this) {createCount++; synchronized (this) {createCount++; synchronized (this) {createCount++; synchronized (this) {createCount++; mapValue = map.put(key, createdValue);if(mapValue ! = null) {// Discard createValue map.put(key, mapValue); }else{ size += safeSizeOf(key, createdValue); }}if(mapValue ! = null) { entryRemoved(false, key, createdValue, mapValue);
            return mapValue;
        } else {
            trimToSize(maxSize);
            returncreatedValue; }}Copy the code

put

Public final V PUT (K key, V value) {// The key value cannot be null.if (key == null || value == null) {
            throw new NullPointerException("key == null || value == null"); } V previous; synchronized (this) { putCount++; Size += safeSizeOf(key, value); previous = map.put(key, value);if (previous != null) {
                size -= safeSizeOf(key, previous);
            }
        }

        if(previous ! = null) { entryRemoved(false, key, previous, value); } // Here is the overflow, recycle. trimToSize(maxSize);return previous;
    }
Copy the code

remove

public final V remove(K key) {
        if (key == null) {
            throw new NullPointerException("key == null");
        }

        V previous;
        synchronized (this) {
            previous = map.remove(key);
            if (previous != null) {
                size -= safeSizeOf(key, previous);
            }
        }

        if(previous ! = null) { entryRemoved(false, key, previous, null);
        }

        return previous;
    }
Copy the code

The trimToSize minimum algorithm is involved here

**public void trimToSize(int maxSize) {
        while (true) { K key; V value; Synchronized (this) {// Linkedhashmap's eldest provides the least used entry. Map.Entry<K, V> toEvict = map.eldest();if (toEvict == null) {
                    break;
                }
                key = toEvict.getKey();
                value = toEvict.getValue();
                map.remove(key);
                size -= safeSizeOf(key, value);
                evictionCount++;
            }

            entryRemoved(true, key, value, null); }} * *Copy the code

conclusion

Do you feel empty after watching these operations? Yes, these operations are just synchronization, fixed entryRmove notifications, nothing else. For the least-used implementation, look at LinkedHashMap.