Class Cache.ConcurrentLinkedHashMap<K,​V>

  • All Implemented Interfaces:
    java.io.Serializable, java.util.concurrent.ConcurrentMap<K,​V>, java.util.Map<K,​V>
    Enclosing class:
    Cache<K,​V>

    static class Cache.ConcurrentLinkedHashMap<K,​V>
    extends java.util.AbstractMap<K,​V>
    implements java.util.concurrent.ConcurrentMap<K,​V>, java.io.Serializable
    A ConcurrentMap with a doubly-linked list running through its entries.

    This class provides the same semantics as a ConcurrentHashMap in terms of iterators, acceptable keys, and concurrency characteristics, but perform slightly worse due to the added expense of maintaining the linked list. It differs from LinkedHashMap in that it does not provide predictable iteration order.

    This map is intended to be used for caches and provides the following eviction policies:

    • First-in, First-out: Also known as insertion order. This policy has excellent concurrency characteristics and an adequate hit rate.
    • Second-chance: An enhanced FIFO policy that marks entries that have been retrieved and saves them from being evicted until the next pass. This enhances the FIFO policy by making it aware of "hot" entries, which increases its hit rate to be equal to an LRU's under normal workloads. In the worst case, where all entries have been saved, this policy degrades to a FIFO.
    • Least Recently Used: An eviction policy based on the observation that entries that have been used recently will likely be used again soon. This policy provides a good approximation of an optimal algorithm, but suffers by being expensive to maintain. The cost of reordering entries on the list during every access operation reduces the concurrency and performance characteristics of this policy.

    The Second Chance eviction policy is recommended for common use cases as it provides the best mix of performance and efficiency of the supported replacement policies.

    If the Least Recently Used policy is chosen then the sizing should compensate for the proliferation of dead nodes on the linked list. While the values are removed immediately, the nodes are evicted only when they reach the head of the list. Under FIFO-based policies, dead nodes occur when explicit removals are requested and does not normally produce a noticeable impact on the map's hit rate. The LRU policy creates a dead node on every successful retrieval and a new node is placed at the tail of the list. For this reason, the LRU's efficiency cannot be compared directly to a LinkedHashMap evicting in access order. Ben Manes

    • Constructor Detail

      • ConcurrentLinkedHashMap

        public ConcurrentLinkedHashMap​(Cache.ConcurrentLinkedHashMap.EvictionPolicy policy,
                                       int maximumCapacity,
                                       Cache.ConcurrentLinkedHashMap.EvictionListener<K,​V>... listeners)
        Creates a new, empty, unbounded map with the specified maximum capacity and the default concurrencyLevel.
        Parameters:
        policy - The eviction policy to apply when the size exceeds the maximum capacity.
        maximumCapacity - The maximum capacity to coerces to. The size may exceed it temporarily.
        listeners - The listeners registered for notification when an entry is evicted.
      • ConcurrentLinkedHashMap

        public ConcurrentLinkedHashMap​(Cache.ConcurrentLinkedHashMap.EvictionPolicy policy,
                                       int maximumCapacity,
                                       int concurrencyLevel,
                                       Cache.ConcurrentLinkedHashMap.EvictionListener<K,​V>... listeners)
        Creates a new, empty, unbounded map with the specified maximum capacity and concurrency level.
        Parameters:
        policy - The eviction policy to apply when the size exceeds the maximum capacity.
        maximumCapacity - The maximum capacity to coerces to. The size may exceed it temporarily.
        concurrencyLevel - The estimated number of concurrently updating threads. The implementation performs internal sizing to try to accommodate this many threads.
        listeners - The listeners registered for notification when an entry is evicted.
    • Method Detail

      • isOverflow

        private boolean isOverflow()
        Determines whether the map has exceeded its capacity.
        Returns:
        Whether the map has overflowed and an entry should be evicted.
      • setCapacity

        public void setCapacity​(int capacity)
        Sets the maximum capacity of the map and eagerly evicts entries until the it shrinks to the appropriate size.
        Parameters:
        capacity - The maximum capacity of the map.
      • capacity

        public int capacity()
        Retrieves the maximum capacity of the map.
        Returns:
        The maximum capacity.
      • size

        public int size()
        Specified by:
        size in interface java.util.Map<K,​V>
        Overrides:
        size in class java.util.AbstractMap<K,​V>
      • clear

        public void clear()
        Specified by:
        clear in interface java.util.Map<K,​V>
        Overrides:
        clear in class java.util.AbstractMap<K,​V>
      • containsKey

        public boolean containsKey​(java.lang.Object key)
        Specified by:
        containsKey in interface java.util.Map<K,​V>
        Overrides:
        containsKey in class java.util.AbstractMap<K,​V>
      • containsValue

        public boolean containsValue​(java.lang.Object value)
        Specified by:
        containsValue in interface java.util.Map<K,​V>
        Overrides:
        containsValue in class java.util.AbstractMap<K,​V>
      • evict

        private void evict()
        Evicts a single entry if the map exceeds the maximum capacity.
      • notifyEviction

        private void notifyEviction​(K key,
                                    V value)
        Notifies the listeners that an entry was evicted from the map.
        Parameters:
        key - The entry's key.
        value - The entry's value.
      • poll

        private Cache.ConcurrentLinkedHashMap.Node<K,​V> poll()
        Retrieves and removes the first node on the list or null if empty.
        Returns:
        The first node on the list or null if empty.
      • offer

        private void offer​(Cache.ConcurrentLinkedHashMap.Node<K,​V> node)
        Inserts the specified node on to the tail of the list.
        Parameters:
        node - An unlinked node to append to the tail of the list.
      • get

        public V get​(java.lang.Object key)
        Specified by:
        get in interface java.util.Map<K,​V>
        Overrides:
        get in class java.util.AbstractMap<K,​V>
      • put

        public V put​(K key,
                     V value)
        Specified by:
        put in interface java.util.Map<K,​V>
        Overrides:
        put in class java.util.AbstractMap<K,​V>
      • putIfAbsent

        public V putIfAbsent​(K key,
                             V value)
        Specified by:
        putIfAbsent in interface java.util.concurrent.ConcurrentMap<K,​V>
        Specified by:
        putIfAbsent in interface java.util.Map<K,​V>
      • remove

        public V remove​(java.lang.Object key)
        Specified by:
        remove in interface java.util.Map<K,​V>
        Overrides:
        remove in class java.util.AbstractMap<K,​V>
      • remove

        public boolean remove​(java.lang.Object key,
                              java.lang.Object value)
        Specified by:
        remove in interface java.util.concurrent.ConcurrentMap<K,​V>
        Specified by:
        remove in interface java.util.Map<K,​V>
      • replace

        public V replace​(K key,
                         V value)
        Specified by:
        replace in interface java.util.concurrent.ConcurrentMap<K,​V>
        Specified by:
        replace in interface java.util.Map<K,​V>
      • replace

        public boolean replace​(K key,
                               V oldValue,
                               V newValue)
        Specified by:
        replace in interface java.util.concurrent.ConcurrentMap<K,​V>
        Specified by:
        replace in interface java.util.Map<K,​V>
      • entrySet

        public java.util.Set<java.util.Map.Entry<K,​V>> entrySet()
        Specified by:
        entrySet in interface java.util.Map<K,​V>
        Specified by:
        entrySet in class java.util.AbstractMap<K,​V>