First, the storage structure
Before JDK1.8, HashMap used the bucket + chain list to implement, the essence is to adopt array + unidirectional linked list data structure. It has a fairly fast query speed primarily because it calculates the location of the store by calculating the hash code. HashMap through the key hashcode to calculate the hash value, different hash values exist in the array of different positions, when the hash value of multiple elements at the same time (so-called hash conflict), the use of linked lists to concatenate them (the list to resolve the conflict), Placed on the array position corresponding to the hash value. The structure diagram is as follows:
In the figure, the purple part represents a hash table, also known as a hash array, each element in the array is a head node of a single-linked list, and the list is used to resolve the conflict, and if different key mappings get the same position in the array, they are placed in a single-linked list.
In JDK1.8, the storage structure of HashMap has changed, it adopts the combination data structure of array + linked list + red-black tree. When a hash value conflicts, a linked list or red-black tree is used to resolve the conflict. When the number of nodes of the same hash value is less than 8 o'clock, the linked list is used, otherwise, the red-black tree is used. This major change is mainly to improve query speed. Its structure is shown below:
Second, put method
The first introduction to the storage structure is to better understand the put method.
Public
{
return putval (hash (key), key, value, false, true);
}
The Put method calls the Putval method, so let's look at it again.
/*
Parameters:
Hash Hash for key
Key The key
value the value to put
onlyifabsent If True, don ' t change existing value
evict if False, the table is in creation mode.
Returns:
previous value, or null if none
*/
FinalV Putval (intHash, K key, V value,BooleanOnlyifabsent,BooleanEvict) {
node<k,v>[] tab; Node<k,v> p;intn, I;
//If table is empty, or if there are no elements, the expansion
if(tab = table) = = NULL | | (n = tab.length) = = 0)
n = (tab = resize ()). length;
//If the first node value is empty, a new first node is created.
//Note: (n-1) & Hash is the real hash value, which is the index stored in the table position. In 1.6, it is encapsulated into the indexfor function.
if(p = tab[i = (n-1) & hash]) = = null)
Tab[i] = NewNode (hash, key, value, NULL);
Else{//Come here, it means the collision, then we have to start dealing with the collision.
Node<k,v> e; K K;
If the first node has the same hash and key value as the element we want to insert, it is recorded first.
if(P.hash = = Hash && (k = p.key) = = Key | | (Key! = null && key.equals (k))))
e = p;
Elseif(pinstanceofTreeNode)//If the type of the first node is a red-black tree type, the element is added according to the red-black tree method
E = ((treenode<k,v>) p). Puttreeval ( This, tab, hash, key, value);
Else{//To this step, the first node type is the linked list type.
for(intBincount = 0;; ++bincount) {
//If you traverse to the end, the element node is appended to the tail first.
if((e = p.next) = = null) {
P.next = NewNode (hash, key, value, NULL);
//When the number of nodes traversed is greater than 8 o'clock, the tree structure is taken.
if(Bincount >= treeify_threshold-1)//-1 for 1st
Treeifybin (tab, hash);
Break;
}
//If we find a node with the same hash and key value as the element we are inserting, stop the traversal. At this point, E has recorded the node
if(E.hash = = Hash && (k = e.key) = = Key | | (Key! = null && key.equals (k))))
Break;
p = e;
}
}
//indicates that a node with the same element is recorded .
if(E! = null) {//Existing mapping for key
V oldValue = E.value;
if(!onlyifabsent | | oldValue = = NULL)
E.value = value;
Afternodeaccess (e);//This is an empty function that can be overridden by the user as needed
returnOldValue;
}
}
++modcount;
//When node +1 is greater than threshold, the capacity is expanded
if(++size > Threshold)
Resize ();
Afternodeinsertion (evict);//This is an empty function that can be overridden by the user as needed
returnNull
}
Reference:
1. Jdk1.8hashmap principle and source code Analysis (Java interview collection)
2, Java class set framework of HashMap (JDK1.8) source analysis
Analysis of put source code in JDK1.8 HashMap