JDK8 HashMap source code analysis

1. putVal method

This method is mainly to do the following things:

(1) first determines whether to initialize HashMap underlying table, if not, the operation proceeds to initialize the table calling resize () method. Note that the initialization table resize method which can operate on the table may be for expansion 

(2) The size of the current key value table and the hash value is calculated corresponding to the key value should valu stored table index value in the table, denoted by i

(3) If the table [i] is empty, creating a node Node (node ​​encapsulates the key, value-related data) stored in the table [i]

(4) If the table [I] already has a value, the value we referred to as p, p affirmative table Note that this element of the table, but may also be the head node in the linked list, this processing is divided into three cases

  <1> If the node key and the key is fully equal to p, then covered oldValue

  <2> if p is a tree ..... (skip did not understand)

  <3> removed than the above two cases, the rear end P certainly hanging a chain, which requires for each element in the list is traversed, the list is determined when the node key are equal to the current put the key, if equal, also covering the oldValue, is new or a new node node, and then hung in the rear end of the list. this will also node list length is determined, and if it exceeds 8, treeifyBin method is called, a chain transfer operation tree

(5) Source

/ * 
* Map put implemented method 
* / 
Final V PutVal ( int the hash, Key K, V value, Boolean onlyIfAbsent, Boolean The evict) { 
    the Node <K, V> [] Tab; the Node <K, V> P; int n-, I; 
    
    // if table is null, is not initialized (jdk8 in, table is used for the first time initialization) 
    IF ((table Tab =) == null || (= n-tab.length) 0 == )
         // a resize () method to initialize table or twice expansion 
        n-= (Tab = a resize ()) length;. 
        
    // table length minus 1 and the hash value of the current key of the operation, that is the key is stored in the table subscript
     // & run, the result is the number of bits are 1 1, otherwise it is 0
     // table whether the stored value corresponding to the current value of the key
    IF ((P = Tab [I = (n--. 1) & the hash]) == null )   // do not have this key, if present, on the fob table
         // Create a new Node, the table stored in the table subscript position i is the slot 
        Tab [i] = the newNode (the hash, Key, value, null ); 
   
   the else { // fob table 
        
        the Node <K, V> E; K K; 
        
        // 1. the data table covering Analyzing , p is the head node as a linked list, the table is stored in the 
        IF (the hash p.hash == && ((K = p.key) == || Key (Key! = null && key.equals (K)) )) 
            E = p;   // p-assignment before coating to e, note: not covered here 
            
        @ 2 where processing tree (skip) 
        the else  IF (pthe instanceof the TreeNode) 
            E = ((the TreeNode <K, V>) P) .putTreeVal ( the this , Tab, hash, Key, value); 
        
        // 3. list, there are conflicting data hash, directly linked to the next node in the original on 
        the else {
             for ( int BinCount = 0;; ++ BinCount) { 
            
                IF ((E = p.next) == null ) { 
                     // the key, value packaged into a node node, and then hung on a p Next 
                    p = the newNode .next (the hash, Key, value, null ); 
                    
                    IF (BinCount> = TREEIFY_THRESHOLD -. 1) // -1 for 1st
                         // chain transfer tree
                        treeifyBin (Tab, the hash);
                     BREAK ; 
                } 
            
                // linked list node data coverage determination, the same note in front of the code segment, it is the data (list head node) in Table overwrite operation 
                IF (= e.hash && the hash = (! (K = e.key) == || key (key = null && key.equals (K)))) 
                     BREAK ; //   if the same key, break out of for loop, execution logic behind 
                p = E; 
            } 
        } 
        // maps into Key 
        IF (! E = null ) { // existing Key mapping for 
            V = oldValue e.Value;
             IF(! onlyIfAbsent || oldValue == null ) 
                e.Value = value;   // with the new value to the value of the old value coverage value 
            afterNodeAccess (E);
             return oldValue;   // return value value before coating 
        } 
    } 
    // Record HashMap modified number 
    ++ ModCount;
     // record the number of key-value mapping, corresponds to the HashMap size 
    IF (size ++> threshold)   // if the size is greater than the threshold, it is necessary for expansion 
        a resize ();
     // removed older data, see here temporarily 
    afterNodeInsertion (the evict);
     return  null ; // return null 
}

 

2. resize method

  This method has two roles, one of the operating table is initialized, one table for expansion of operations. In principle, each twice the expansion. The focus of this approach is to look at how it will be transferred oldTab the elements and going to newTab .

  Source used for the loop, each element traversing the oldTab in, we referred to as e, then e is related attribute determination, the same is divided into three cases

(1) If e.next == null, i.e., show no rear butt with the e node tree, nor with the chain, i.e. no hash is e.key of conflict. Thus most simple case, by calculating the value then & e.hash table length after expansion, e is the storage position of the newTab

(2) e where tree node is skipped

(3) where e is the rear end hanging chain, did not see too understand

  Display source, by e.hash & oldCap hang behind the buttocks e list split into two lists, and the two new analysis chain hanging on the two slots newTab. Magic comparison here, the original in the same a linked list data structure (oldTab), with a hash conflict, now through expansion, two slots on the hanging newTab, indicating that these two slots do not exist in the hash key conflict, which is not from the side , expansion reduces the chances of hash conflict.

 

 

Source

 

// to initialize HashMap underlying table or expansion 
Final the Node <K, V> [] a resize () {
     // 1. The original table assigned to the variable oldTab 
    the Node <K, V> [] = oldTab table;
     // oldTab the capacity value, namely the original table in the number of elements 
    int OLDCAP = (oldTab == null ) 0? : oldTab.length;
     //   original expansion threshold 
    int oldThr = threshold;
     // define two variables, the new table and capacity threshold 
    int newCap, newThr = 0 ;
     IF (OLDCAP> 0) { // denote the table elements have 
        IF (OLDCAP> = MAXIMUM_CAPACITY) {   // if the number of elements of the original table (before expansion) is greater than or equal 1073741824
            = Integer.MAX_VALUE threshold;   // directly sets the threshold value to the Integer value Max_VALUE 
            return oldTab; 
        } 
        // newCap expansion OLDCAP basis of 1 times 
        the else  IF ((newCap = OLDCAP << 1) <MAXIMUM_CAPACITY && OLDCAP> = DEFAULT_INITIAL_CAPACITY) 
            newThr = oldThr <<. 1; // Double threshold 
    }
     the else  IF (oldThr> 0) // Initial Capacity WAS Placed in threshold 
        newCap = oldThr;
     the else {                // ZERO Initial threshold signifies the using Defaults 
        newCap =DEFAULT_INITIAL_CAPACITY; 
        newThr = ( int ) (* DEFAULT_LOAD_FACTOR DEFAULT_INITIAL_CAPACITY); 
    } 
    IF (newThr == 0 ) {
         a float . Ft = ( a float ) newCap * loadFactor; 
        newThr = (newCap <&& MAXIMUM_CAPACITY. Ft <( a float ?) MAXIMUM_CAPACITY ( int ). Ft : Integer.MAX_VALUE); 
    } 
    threshold = newThr; 
    
    
    // here is the first use of table initialize 
    the Node <K, V> [] = newtab (the Node <K, V> []) new new the Node [newCap] ; 
    Table = newtab; //The initialization of this newTab assigned to the table 
    
    
    
    // The following should be the focus: expansion (expansion table in front of the elements to the table after the expansion to go) if it is initialized, will not enter inside if conditions go. 
    If (oldTab =! null ) {
         // iterate removed before expansion of each table element for loop 
        for ( int J = 0; J <OLDCAP; ++ J) { 
            the Node <K, V> E;
              // only for non-empty elements processing 
            IF (! (e = oldTab [j]) = null ) {    // element j-th position oldTab taken out will be assigned to the variable e 
                oldTab [j] = null ;     // the j-th position in the opposite oldTab empty 
                
                // below this is the logic table before expansion in the expansion element is moved to the table, particularly divided into three cases
                 //1. The first case is the most simple, no hash conflicts, that is listless 
                IF (e.next == null ) 
                    newtab [e.hash & (newCap - 1)] = e;   // e is the element into newTab (table after expansion) of e.hash & (newCap - 1) in this position 
                
                // have hash conflicts, and the latter has been turned into a red-black tree list 
                the else  IF (E the instanceof the TreeNode) 
                    ((the TreeNode < K, V>) E) .split ( the this , newtab, J, OLDCAP); 
                
                // with a hash conflict, but still behind lists 
                the else { 
                    the Node <K, V> loHead = null , loTail = null ; 
                    the Node <K, V > hiHead = null, HiTail = null ; 
                    the Node <K, V> Next; 
                    
                    // This will do ... while loop oldTab [j] of the node list elements are later hung on two lists, one for LO ...., a is hi ...., 
                     @ then lo, two split hi chain hanging out at different locations of the expansion of the newTab
                     @ feeling or not understand ... 
                    do { 
                        Next = e.next;
                         IF ((e.hash & OLDCAP) == 0) { // LO list .. 
                            IF (loTail == null ) 
                                loHead = E;
                             the else 
                                loTail.next= e;
                            loTail = e;
                        
                        }else {   // hi..链表
                            
                            if (hiTail == null)
                                hiHead = e;
                            else
                                hiTail.next = e;
                            hiTail = e;
                        }
                    } while ((e = next) != null);
                    
                    
                    if (loTail != null) {
                        loTail.next = null ; 
                        newTab [j] = loHead;   // the lo chain linked to newTab [j] position 
                    }
                     IF (hiTail =! null ) { 
                        hiTail.next = null ; 
                        newtab [J + OLDCAP] = hiHead;   // the hi chain linked to newTab [j + oldCap] position 
                    } 
                } 
            } 
        } 
    } 
    return newtab; 
}

 

 

 To be continued ..... etc.

  

  

  

Guess you like

Origin www.cnblogs.com/z-qinfeng/p/12115647.html