Java Linkedhashmap class Source parsing

Source: Internet
Author: User
Tags joins

Linkedhashmap inherited the HashMap, he added a two-way list structure on the basis of HashMap, the list is maintained by default key insertion order, the duplicate key value insertion does not change the order, for the user needs to return a sequence of the same map object case. You can also generate Access-order sequential versions, which are stored in the order of recent accesses, the nodes that have just been accessed are at the end of the list, and suitable for the lru,put get compute merge to count as one access, where a node with the same put key value counts as a single access. Replace is only one access when replacing a key-value pair, and the order of access generated by Putall depends on the iterator implementation of the original map.

When you insert a key-value pair, you can automatically delete the oldest key-value pair when inserting by using the Removeeldestentry override to implement the new key value pair

With the method provided by the HashMap, the iterator because is traversed by the bidirectional list, so the extra overhead is proportional to the size of the capacity independent, so the selection of the initial size of the traversal time of the increase is not hashmap serious, the latter of the traversal time dependence and capacity.

Also is a non-thread-safe method, for Linkedhashmap, to modify the structure of the operation in addition to increase and delete the key value of the external, and for Access-order when access causes the iterator order changes, mainly get operations, for the insertion Order, Just modifying the value of an existing key value is not an operation to modify the structure, but for the access order, the put and get existing key values change the order. Iterators are also fail-fast designed, but Fail-fast is just a debugging feature and a well-designed program should not have this error

Because HashMap joined TreeNode, so now Linkedhashmap has this function as well.

The linked list in the following description, if not specifically stated, refers to the Linkedhashmap doubly linked list

Take a look at the basic structure, each key-value pair joins the front and back pointers, the collection joins the tail-up pointer to form a doubly linked list, accessorder to indicate whether the linked list is stored in order of access or insert sequence

    Static classEntry<k,v>extendsHashmap.node<k,v>{Entry<K,V> before, after;//added a pointer to form a doubly linked listEntry (intHash, K key, V value, node<k,v>next) {            Super(hash, key, value, next); }    }    /*** The head (eldest) of the doubly linked list.*/    transientLinkedhashmap.entry<k,v>Head; /*** The tail (youngest) of the doubly linked list. Tail*/    transientLinkedhashmap.entry<k,v>tail; //true Access order false Insert order    Final BooleanAccessorder;

Then there are several internal methods. Linknodelast connecting p to the tail of the list

    Private void linknodelast (linkedhashmap.entry<k,v> p) {        linkedhashmap.entry<K,V> last = tail;         = p;         if NULL )            = p; // If the linked list is empty then P is also the head        Else {            = last ;             = p;        }    }

Transferlinks replacing SRC with DST

    Private voidTransferlinks (linkedhashmap.entry<k,v>src, linkedhashmap.entry<K,V>DST) {Linkedhashmap.entry<K,V> b = Dst.before =Src.before; Linkedhashmap.entry<K,V> A = Dst.after =Src.after; if(b = =NULL) Head=DST; ElseB.after=DST; if(A = =NULL) Tail=DST; ElseA.before=DST; }

Reinitialize the head and tail are set to NULL based on the call to the HashMap method

    void reinitialize () {        Super. Reinitialize ();         NULL ;    }

NewNode generates a Linkedhashmap node, next points to E, and inserts to the end of the Linkedhashmap list

    Node<k,v> newNode (int hash, K key, V value, node<k,v> e) {        linkedhashmap.entry<k,v > P =            new linkedhashmap.entry<k,v> (hash, key, value, e);   Create a new key-value pair, next points to E        linknodelast (p);   p Insert to the end of the Linkedhashmap list        return  p;    }

Replacementnode generates a LINKEDHASHMAP node to replace the original node based on the Origin node.

    Node<k,v> Replacementnode (node<k,v> p, node<k,v> next) {        linkedhashmap.entry<K,V > q = (linkedhashmap.entry<k,v>) p;        Linkedhashmap.entry<K,V> t =            new linkedhashmap.entry<k,v> (Q.hash, Q.key, Q.value, Next ); // generate a new key value pair Next is given next parameter        Transferlinks (q, T); // Replace Q        with T return t;    }

Newtreenode generates a TreeNode node, next points to next, inserts to the end of the Linkedhashmap list

    Treenode<k,v> newtreenode (int hash, K key, V value, node<k,v> next) {        TreeNodeNew treenode<k,v> (hash, key, value, next); // generates a treenode,next pointing to the parameter next        Linknodelast (P); // p insert to end        of Linkedhashmap list return p;    }

Replacementtreenode generates a new treenode,next based on the node p and sets it to the given next, replacing the original p

    Treenode<k,v> Replacementtreenode (node<k,v> p, node<k,v> next) {        linkedhashmap.entry <K,V> q = (linkedhashmap.entry<k,v>) p;        TreeNodeNew treenode<k,v>(Q.hash, Q.key, Q.value, next);        Transferlinks (q, t); // generate a new treenode,next based on the node p set to the given next, replacing the original P        return t;    }

Afternoderemoval removing nodes from the Linkedhashmap chain E

    voidAfternoderemoval (node<k,v>e) {linkedhashmap.entry<K,V> p =(Linkedhashmap.entry<K,V>) E, B = p.before, a =P.after; P.before= P.after =NULL; if(b = =NULL) Head=A; ElseB.after=A; if(A = =NULL) Tail=b; ElseA.before=b; }

Afternodeinsertion may remove the oldest node, need evict to true while the linked list is not empty and removeeldestentry need to be rewritten

    void afternodeinsertion (boolean  evict) {         linkedhashmap.entry<K,V> first ;         ifnull && removeeldestentry (first)) {//removeeldestentry needs to be rewritten before it works, Otherwise it must return false            K key = First.key;   Remove the node of the linked list header            nullfalsetrue);        }    }

Afternodeaccess after the visit, the node E is moved to the tail of the list, need map is access-order, if the move is successful increase modcount

    voidAfternodeaccess (node<k,v>e) {linkedhashmap.entry<K,V>Last ; if(Accessorder && (last = tail)! = e) {//map is Access-order and E is not the tail of the list.Linkedhashmap.entry<k,v> p =(Linkedhashmap.entry<K,V>) E, B = p.before, a =P.after; P.after=NULL; if(b = =NULL)//Cut the node e from the linked list .Head =A; ElseB.after=A; if(A! =NULL) A.before=b; Else Last=b; if(Last = =NULL) Head=p; Else{P.before=Last ; Last.after=p; } Tail= P;//node E moves to the tail of the list.++modcount;//because there are access-order below the node is moved, so increase modcount        }    }

In terms of constructors, the Accessorder default is the insertion order, the initial size is 16, the load factor is 0.75, and this is the same as HashMap. The copy construct also calls the Hashmap.putmapentries method

The

Containsvalue iterates through the list looking for an equal value, and this operation must not cause a structural change

 public  boolean   Containsvalue (Object value) { for  (LINKEDHASHMAP.ENTRY<K,V&G T e = head; E! = null ; E = e.after) {//  The check is also traversed according to the list of links provided by Linkedhashmap             v v = E.value;  if  (v = = value | |                (Value! = null  && Value.equals (v)))  return  true         ;  return  false  ; }

The Get method uses the GetNode method of the HashMap, if the node is found and the map is the access order, the Access node is placed at the end of the list, and null is returned if it is not found. And Getordefault's only difference is that when it's not found, it returns defaultvalue

     PublicV get (Object key) {Node<K,V>e; if(E = getnode (hash (key), key) = =NULL)//GetNode method for multiplexing HashMap            return NULL; if(Accessorder) afternodeaccess (e);//put E at the end of the Access-order.        returnE.value; }     Publicv Getordefault (Object key, v DefaultValue) {Node<K,V>e; if(E = getnode (hash (key), key) = =NULL)           returnDefaultValue;//The GetNode method for multiplexing HashMap returns defaultvalue if no corresponding node is found .       if(Accessorder) afternodeaccess (e);//put E at the end of the Access-order.       returnE.value; }

The Clear method sets head and tail to null on a hashmap basis

     Public void Clear () {        Super. Clear ();         NULL ;    }

Removeeldestentry is called when the put and Putall insert a key-value pair, the original must return FALSE, if you want to automatically delete the oldest key-value pair to return true, you need to rewrite. For example, the control size cannot exceed 100

    Private Static Final int Max_entries = +;      protected Boolean Removeeldestentry (map.entry eldest) {        return size () &gt; max_entries;     }

The following two methods are similar to HashMap, which returns the set of key and the collection of value and the set of return key-value pairs, this is a direct reference, so modifications to their remove are directly fed back to Linkedhashmap

     PublicSet<k>KeySet () {Set<K> KS =KeySet; if(KS = =NULL) {KS=NewLinkedkeyset (); KeySet=KS; }        returnks//returns the set of the key value    }     PublicCollection<v>values () {Collection<V> vs =values; if(vs = =NULL) {vs=Newlinkedvalues (); Values=vs; }        returnvs//returns a collection that contains all value values    }     PublicSet<map.entry<k,v>>EntrySet () {Set<Map.Entry<K,V>>es; return(es = entryset) = =NULL? (EntrySet =NewLinkedentryset ()): es;//returns a set containing all key-value pairs}

Checking the Putval method of HashMap, we can see that afternodeaccess is called when the same key value is found and the value is modified, and the node order is changed for Access-order

            if NULL // The same key is found, the value is modified and the old value                is returned. V oldValue = e.value;                 if NULL )                    = value;                Afternodeaccess (e);                 return oldValue;            }

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.