A preliminary study on Linkedhashmap

Source: Internet
Author: User

Code encountered LRUCache data structure, carefully study the bottom is a LINKEDHASHMAP basic data structure, and decided to simply summarize the linkedhashmap source.

public class linkedhashmap<k,v>
    extends hashmap<k,v>
    implements Map<k,v>
It can be seen that Linkedhashmap is inherited from the HashMap class and is also an implementation of the map structure. What is the difference between the internal implementation structure of the Linkedhashmap and the HashMap, in one sentence to sum up:

LINKEDHASHMAP maintains all nodes in the HashMap as a two-way cyclic list structure based on the original hash table structure of HashMap. Thus the LINKEDHASHMAP can support the traversal of access by Key-value Insertion Order (Insertion-order) or access order (Access-order). 1. Entry class rewrite for HashMap In Linkedhashmap, the entry class in HashMap is rewritten, which is the basic data structure to realize bidirectional cyclic chain list.

/** * Linkedhashmap entry. * * private static Class Entry<k,v> extends Hashmap.entry<k,v> {//These fields comprise the DOUBL
        Y linked list used for iteration.    Entry<k,v> before, after; The precursor node and successor node pointer Entry (int hash, K key, V value, hashmap.entry<k,v> next) {Super (hash, key, value    , next);
         Constructors directly call the constructor of the parent class}/** * Removes this entry from the linked list.
            * * private void Remove () {//delete operation Before.after = after;
        After.before = before;
         }/** * Inserts this entry before the specified existing in the list.
            * * private void Addbefore (entry<k,v> existingentry) {//insert operation after = Existingentry;
            before = Existingentry.before;
            Before.after = this;
        After.before = this; }/** * This is invoked by the superclass whenever the value * of a pre-existing entry is read by Map.get or modified by Map.set. * If The enclosing Map is access-ordered, it moves the entry * to the end of the list;
         Otherwise, it does nothing. */void Recordaccess (hashmap<k,v> m) {//rewrite the recordaccess function of the parent class to maintain the bidirectional linked list Linkedha
            shmap<k,v> lm = (linkedhashmap<k,v>) m;
                if (lm.accessorder) {lm.modcount++;
                Remove ();                        Addbefore (Lm.header);                 Here's an important point: before you move the most recently accessed node to the virtual header node of a two-way list,} void Recordremoval (hashmap<k,v> m) {
        Overrides the Recordremoval function of the parent class remove (); }
    }

2. Constructors mainly describe a constructor with the most parameters, and the other constructors simply set the relevant data field to the default value.

/**
     * Constructs a empty <tt>LinkedHashMap</tt> instance
     with the * specified initial, load Factor and ordering mode.
     * *
     @param  initialcapacity The initial capacity
     * @param  loadfactor The      load factor
     * @param C10/>accessorder     The ordering mode-<tt>true</tt>
     for *         Access-order, <tt>false </tt> for Insertion-order
     * @throws IllegalArgumentException If the initial capacity is negative
     *         Or the load factor is nonpositive
     *
    /public linkedhashmap (int initialcapacity,
			 float loadfactor,
                         Boolean Accessorder) {
        super (initialcapacity, loadfactor);
        This.accessorder = Accessorder;       Used to determine the maintenance of the current Linkedhashmap bidirectional cyclic link, i.e. Accessorder and Insertionorder
    }
You can see the constructors that call the parent class at the main time, while initializing the maintenance of the bidirectional cyclic list.
    /**
     * Called by superclass Constructors and Pseudoconstructors (clone,
     * readobject) before the any entries are insert Ed into the map.  Initializes
     * the chain.
     *
    /void init () {
        Header = new entry<k,v> ( -1, NULL, NULL, NULL);
        Header.before = Header.after = header;         Initializes a virtual header node for a bidirectional cyclic list
    
Here's a point to note when header statement:
/** * The head of the
     doubly linked list.
     * *
    private transient entry<k,v> header;
The transient keyword is used in health, meaning that when a linkedhashmap is serialized, the header node is not included, that is, the header node does not store the truly meaningful data fields. 3.put OperationInstead of rewriting the put operation in HashMap, Linkedhashmap overrides the AddEntry function.
/**
     * This override alters behavior of the superclass put method. It causes newly * allocated entry to get inserted in the end of the
     linked list and
     * Removes the eldest entry if appropriate.
     * *
    void addentry (int hash, K key, V value, int bucketindex) {
        createentry (hash, key, value, Bucketindex);

        Remove eldest entry if instructed, else grow capacity if appropriate entry<k,v>
        = eldest;
        if (Removeeldestentry (eldest)) {                                   //whether to delete the least Access node
            removeentryforkey (Eldest.key);        Here the eliminated node is always when the after node of the header node 
        } else {                                 //is treated in the same way as in HashMap, increasing capacity to rebuild the hash
            if (size >= threshold)
                Resize (2 * table.length);
        }
    
The more interesting function here is
Removeeldestentry (eldest)
If you're interested in reading this note, you'll find that he actually sees it as an extensible interface for the programmer to implement the cache, which means that you can implement the cache for the specified policy by inheriting and overriding the function in your own cache class. If you set Accessorder to True and follow the example in the annotation, the LRU is implemented, and if you use the default Accessorder as false, the first inserted priority is guaranteed to be deleted if you follow the example rewrite in the annotation.
/** * Returns <tt>true</tt> If this map should the remove its eldest entry. * This (IS) invoked by <tt>put</tt> <tt>putAll</tt> on * Inserting a new entry in  to the map.  IT provides the implementor * with the opportunity to remove the eldest entry for each time a new one * is added. This is useful if the map represents a cache:it allows * the map to reduce memory consumption by deleting stale
     ies.  * * <p>sample Use:this Override'll allow the map to grow up to * entries and then delete the eldest
     Entry a new entry is * added, maintaining a steady state of entries.
     * <pre> * private static final int max_entries = 100;
     * * Protected Boolean removeeldestentry (Map.entry eldest) {* return size () > max_entries; * </pre> * * <p>this method typically does is not modify the map by any way,
     * Instead allowing the map to modify itself as directed through its * return value. It <i>is</i> permitted to modify * The map directly, but if it does, it <i>must& lt;/i> return * <tt>false</tt> (indicating, the map should not attempt any * further Modifica  tion). 
     The effects of returning <tt>true</tt> * After modifying's map from within this method are unspecified.  * * <p>this implementation merely returns <tt>false</tt> (so, this * map acts like a
     Normal map-the eldest element is never removed). * * @param eldest the least recently inserted entry in the map, or if *-is a access-ordered m  AP, the least recently accessed * entry.  This are the entry that would be removed it this * method returns &LT;TT&GT;TRUE&LT;/TT&GT;. If the map is empty prior * to the &LT;TT&GT;PUT&LT;/TT> or <tt>putAll</tt> invocation resulting * Invocation, this is the entry that was just * inserted;
     In other words, if the map contains a single * entry, the eldest entry is also the newest. * @return <tt>true</tt> If the eldest entry should is removed * from the map;
     <tt>false</tt> if it should be retained.
    * * Protected Boolean removeeldestentry (map.entry<k,v> eldest) {return false; }
A new Key-value insertion is implemented through the Createentry
    /**
     * This override differs from addentry into that it doesn ' t resize the
     * table or remove the eldest entry.
     * *
    void createentry (int hash, K key, V value, int bucketindex) {
        hashmap.entry<k,v> old = Table[bucketindex] ;
	entry<k,v> e = new entry<k,v> (hash, key, value, old);     
        Table[bucketindex] = e;      Three steps ensure that the insertion is always in the bucketindex of the adjacent chain header
        E.addbefore (header);         Maintains a two-way cyclic list where the newly inserted node is always in front of the header
        size++;
    
This is the first thing to put.
4.get OperationLinkedhashmap rewrite the HashMap get operation, there is nothing to say, according to the key query time complexity has not changed
    /** * Returns the value to which the specified key was mapped, * or {@code null} If this map contains no Mapp
     ing for the key.  * * <p>more formally, if this map contains a mapping from a key * {@code k} to a value {@code v} such {@code (key==null k==null: * key.equals (k))}, then this method returns {@code V};  otherwise * It returns {@code null}.
     (There can be at most one such mapping.) * <p>a return value of {@code null} does not <i>necessarily</i> * indicate that map cont Ains no mapping for the key;
     It's also * possible this map explicitly maps the key to {@code null}.
     * The {@link #containsKey ContainsKey} operation May is used to * distinguish these two cases.  * * Public V get (Object key) {entry<k,v> E = (entry<k,v>) getentry (key);
        Call Getkey if (E = = null) of the parent class return null;                      E.recordaccess (this); AdjustableThe recordaccess can be used to maintain the bidirectional linked list return e.value in appropriate cases; }
5. Some functions that are optimizedContainsvalue The original HashMap is optimized by traversing the bidirectional linked list directly.
/**
     * Returns <tt>true</tt> If this map maps one or more keys to the
     * specified value.
     *
     * @param value value whose presence in this map are tested
     * @return <tt>true</tt> if this map Maps one or more keys to the
     *         specified value
     *
    /public boolean containsvalue (Object value) {
        //Ove Rridden to take advantage of faster iterator
        if (value==null) {for
            (Entry e = header.after; e!= header; e = e. After)
                if (e.value==null) return is
                    true;
        } else {for
            (Entry e = header.after e!= header; e = e.after)
                if (value.equals (E.value)) return
                    true;
        }
        return false;
    }

6. SummaryLinkedhashmap through the definition of entry rewrite in map, a bidirectional cyclic list is maintained on the basis of the original hash table data structure, which records the insertion/access order in map, and rewrites the iterator. Linkedhashmap also does not have any thread synchronization operations, so multithreading concurrent access is not supported.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.