Java 8 before ：
The underlying implementation is an array + Linked list , The main member variables are ： Storing data table array , Number of key value pairs size, Load factor loadFactor.
table Array for recording HashMap All data for , Each subscript of it corresponds to a linked list , All hash conflict data will be stored in the same linked list ,Entry
Is a node element of a linked list , Contains four member variables ： key key, value value, Execute pointer to next node next and Hash value of element hash.
stay HashMap The data in is in the form of key value pairs , Key corresponding hash Value will be used as its subscript in the array , If two elements key Of hash
Same value , Will send hash conflict , Is placed on a linked list in the same subscript , In order to HashMap As efficient as possible , Should make the hash Values are as scattered as possible .
HashMap The default initialization capacity is 16, Expansion capacity must be 2 Power of , The maximum capacity is 1<< 30 , The default load factor is 0.75.
1 put method ： Add element
① If key by null value , Direct deposit table.
② If key Not for null value , Calculate first key Corresponding hash value .
③ call indexFor Method basis key The hash value of and the length of the array i.
④ ergodic table[i] Corresponding linked list , If key Already exists , Update it value Value and return the old value value .
⑤ If key non-existent , I will modCount Value plus of 1, use addEntry Method to add a node , And return null value .
2 hash method ： Calculation element key Corresponding hash value
① handle String When data of type , Call the corresponding method directly to get the final hash value .
② When processing other types of data , Provide a relative HashMap The unique random value of an instance hashSeed As the initial quantity of calculation .
③ Perform exclusive or and unsigned move right operations to hash Values are more discrete , Reduce the probability of hash conflict .
3 indexFor method ： Calculate element subscript
Directly hash Values and array length - 1 Carry out and operate and return , Ensure that the calculated result will not exceed table Array length range .
4 resize method ： according to newCapacity To determine the new expansion threshold threshold
① If the current capacity has reached the maximum capacity , Set the threshold value to Integer Max of , After that, the expansion will not trigger again .
② Create a new capacity of newCapacity Of Entry array , And call transfer Method to transfer the elements of the old array to the new array .
③ Set threshold to （newCapacity And load factor loadFactor Product of ） and （ Maximum capacity + 1 ） The smaller of .
transfer： Transfer old array to new array
① Traverse all elements of the old array , call rehash Method to determine whether hash reconstruction is needed , Recalculate elements if necessary key Hash value of .
② call indexFor Method basis key The hash value of and the length of the array i, Transfer the elements of the old array to the new array .
5 get method ： according to key Get element's value value
① If key by null value , call getForNullKey method , If size by 0 Indicates that the list is empty , return null value . If size Not for
0, Indicates that there is a linked list , ergodic table List of , If you find it key by null The node of returns its value value , Otherwise return null value .
② call getEntry method , If size by 0 Indicates that the list is empty , return null value . If size Not for 0, Calculate first key
Hash value of , Then traverse all nodes of the list , If the node's key Values and hash If the value is the same as the element to be found, it will be returned Entry node .
③ If the corresponding Entry node , use getValue Method to get its value Value and return , Otherwise return null value .
Java 8 after ：
Using arrays + Linked list / The form of Mangrove ,table Array element data type changed to Entry Static implementation class of Node.
1 put method ： Add element
① call putVal Method add element .
② If table Expand when empty or no element , Otherwise calculate element subscript position , If it doesn't exist, create a new node to store .
③ If the hash Values and key Same value , Direct update value value .
④ If the first node is TreeNode type , call putTreeVal
Method to add a tree node , Compare the size of the inserted node and the current node each time , When the node to be inserted is small, search to the left subtree , Otherwise, search right subtree , Two methods are executed after finding the empty space ：balanceInsert
method , On the one hand, insert the node into the red black tree , On the one hand, adjust and balance the red and black trees .moveRootToFront method , Due to the balance adjustment of red and black trees
root Nodes may change ,table The node recorded in is no longer the root node , Root node needs to be reset .
⑤ If it is a linked list node , Just traverse the list , according to hash Values and key
Value judgment is repeated , Decide whether to update the value or add a new node . If you traverse to the end of the list , Add linked list element , If the tree building threshold is reached , You also need to call treeifyBin Method to reconstruct the linked list into a red black tree .
⑥ After storing elements , take modCount Value plus 1, If the number of nodes + 1 Greater than capacity expansion threshold , Capacity expansion is also needed .
2 get method ： according to key Get element's value value
① call getNode Method acquisition Node node , If not null Value returns Node Node's value value , Otherwise return null.
② If the array is not empty , Compare the first node with the hash Values and key value , If both are the same, return directly .
③ If the second node is TreeNode Nodes call getTreeNode Method to find , Otherwise, traverse the list according to hash Values and key
Value to find , Return if not found null.
3 hash method ： Calculation element key Corresponding hash value
Java 8 It's a lot easier , If key Will not be empty key Of hashCode()
High and low return value 16 Bit for exclusive or operation , This is mainly to let as many bits as possible participate in the operation , Let the 0 and 1 More evenly distributed , So as to reduce the probability of hash conflict .
4 resize method ： Expand array
Re planning length and thresholds , If the length changes , Some data nodes also need to be rearranged .
Re planning length
① If size Capacity expansion threshold exceeded , hold table Increase capacity to previous 2 times .
② If new table Capacity less than default initialization capacity 16, Then table Capacity reset to 16.
③ If new table Capacity is greater than or equal to the maximum capacity , Then set the threshold value to Integer Max of , also return Termination of capacity expansion , because size
It is impossible to exceed this value, so the capacity expansion will not occur later .
Rearrange data nodes
① If the node is null Value is not processed .
② If the node is not null Value and no next node , Then recalculate its hash value and store the new table In array .
③ If the node is TreeNode node , Then call split Method , This method is used to adjust the red black tree , If it is too small, it will degrade back to the linked list .
④ If the node is a linked list node , The linked list needs to be split into hashCode() Return the list whose value exceeds the old capacity and the list whose value does not exceed the capacity . about hash & oldCap == 0
The part of does not need to be processed , On the contrary, it needs to be placed in a new subscript position , New subscript = Old subscript + Old capacity .
supplement ： Mangrove
Red black tree is a self balanced binary search tree .
Each node of the red black tree can only be red or black , The root node is black , Every leaf node is black , If a leaf node is red , Its child nodes must be black , All paths from a node to its leaf nodes contain the same number of black nodes .
Sinistral ： Yes a Node left turn , Refer to general a Right node of node as a Parent node of , soon a Become a left node .
Dextral ： Yes a Node rotate right , Refer to general a Left node of node as a Parent node of , soon a Become a right node .
The addition of red black tree is divided into 3 step ：① Consider red black tree as a binary search tree , And insert the new node with the insertion rule of binary tree .② Set the inserted node to red or black .③
Through left , Right handed or discolored , Make it a red black tree again .
According to the parent node of the inserted node , Inserts can be divided into 3 Case handling ：
* The inserted node is the root node , Paint it black directly .
* The parent of the inserted node is black , No processing , Red black tree after node insertion .
* The parent of the inserted node is red , There must be non empty grandfather nodes , Further divided into three situations ：
* Uncle node is red , Set parent node to black , Uncle node set to black , Grandfather node set to red , Make grandfather node the current node .
* Uncle node is black and current node is right node , Set the parent node as the current node , Rotate left with the new node as the fulcrum .
* Uncle node is black and current node is left , Set the parent node to black , Grandfather node set to red , Rotate right with grandfather node as pivot .
The addition of red black tree is divided into 3 step ：① Consider red black tree as a binary search tree , And delete the new node with the delete rule of binary tree .② Through left , Right handed or discolored , Make it a red black tree again .
According to the deleted node , Delete can be divided into 3 Case handling ：
* The deleted node has no children , Delete it directly .
* The deleted node has only one child , Delete the node directly , And replace its location with its unique child node .
* The inserted node has two children , Find the replacement node of this node first , Then copy the value of the replacement node to the node , Delete replacement node .
Through left , To turn right or change color to make a redwood . If the current node's child nodes are one red one black , Set the node to black directly . If the current node's children are all black , And the current node is the root node , Do not handle . If the current node's children are all black and the current node is not the root node , It can be divided into the following situations ：
* The sibling of the current node is red , Set the sibling of the current node to black , Set parent node to red , Rotate left to parent node , Reset the sibling of the current node .
* The sibling of the current node is black , The two child nodes of brother nodes are also black , Set the sibling of the current node to red , Make the parent of the current node the new node .
* The sibling of the current node is black , Brother node's left node is red, right node is black , Set the left child of the current node to black , Set brother node to red , Right turn brother node , Reset sibling .
The sibling of the current node is black , The right node of brother node is red , Assign parent node of current node to sibling node , Set parent node to black , Set the right child of the sibling node to black , Rotate left to parent node , Set current node as root node .