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.