The HashMap principle of the Java series

Source: Internet
Author: User

Class diagram

Before formally analyzing the principle of hashmap implementation, let's look at its class diagram.

SOURCE Interpretation

The following collection HashMap the put (K key, V value) method to explore its implementation principle.

//Inside the HashMap for inserting data is a one-dimensional array of node objects named "Table"The //node object is a data structure that actually holds the insert key and valuetransientNode<k,v>[] table;//External Call interface method for inserting data PublicVput(K key, V value) {return Putval(Hash(key), key, value,false,true);}//Internal real data insertion methodFinalVPutval(intHash, K key, V value,BooleanOnlyifabsent,BooleanEvict) {node<k,v>[] tab; Node<k,v> p;intn, I;if(tab = table) = =NULL|| (n = tab.)length) ==0)Initialize table array when inserting data for the first timen = (tab =Resize()).length;if(p = Tab[i = (N-1) (& hash]) = =NULL)The //variable n is the current capacity of HashMap, which is actually the size of the table array        //Will (N-1) and insert Data key hashcode value of logic and operation, find a random position I        //If table[i] value is NULL, indicating that the location has not yet stored data, creates a new node object and stores it in Table[i], this time, the insertion is complete, return null valueTab[i] =NewNode(hash, key, value,NULL);Else{//If the Table[i] value is not NULL, it means that the location has already stored the data and continues to look for the location where the data was insertedNode<k,v> e; K K;if(p.Hash= = Hash && (k = p.Key) = = Key | | (Key! =NULL&& key.equals(k))))//If the hashcode value of the newly inserted data key is the same as the Hascode value of the table[i] position holding object key            //And new Insert Data key and Table[i] position the key that holds the object refers to the same object or they are equal (compared by the Equals method)            //The value of the object is stored with the value of the newly inserted data table[i] position, and the value of the object that was previously stored in the location is returned with the insertion complete.e = p;Else if(pinstanceofTreeNode)//If table[i] position the object belongs to the TreeNode type for special handling            //Why do you need to determine if the TreeNode type? E = ((treenode<k,v>) p).Puttreeval( This, tab, hash, key, value);Else{//If the new Insert Data key is not the same as the Table[i] Position object key, then look for a location that meets the following criteria, inserting the new data into the corresponding location            //Condition 1: If the next property of the Table[i] position object is null, the new node object is referenced directly through the next property, and Null is returned            //Condition 2: If the next property of the Table[i] Location object is not NULL, look for a location on the list of objects to insert the new data, which is handled according to the following criteria            //Condition 3: If the key of the inserted data is the same as the key of a node object on the linked list, replace the value of the node object with the newly inserted value and return the value of value before the node            //If the appeal 3 conditions are not met, the inserted data is saved at the end of the Table[i] Position object list and returns null            //Summary: HashMap The actual data is a one-dimensional array, and each array element supports the list structure             for(intBincount =0; ; ++bincount) {if((e = P.)Next) ==NULL) {p.Next=NewNode(hash, key, value,NULL);if(Bincount >= Treeify_threshold-1)//-1 for 1st                        Treeifybin(tab, hash); Break; }if(E.Hash= = Hash && (k = e.Key) = = Key | | (Key! =NULL&& key.equals(k)))) Break;            p = e; }        }if(E! =NULL) {//Existing mapping for keyV OldValue = e.value;if(!onlyifabsent | | oldValue = =NULL) E.value= value;afternodeaccess(e);returnOldValue; }} ++modcount;if(++size > Threshold)Resize();afternodeinsertion(evict);return NULL;}

The above HashMap implementation of inserting data into the process to insert 4 data for the example is described as follows:
1. When inserting the first data, initialize the HASHMAP internal one-dimensional array named "table", the default size is 16, and each array element value is null.

Looking for an Insert data position I, this implementation in HashMap is very ingenious, this insertion position is calculated by the following expression: i = (n - 1) & hash . where n is the capacity of the current HashMap, is actually the size of the internal table array, hash is the hashcode value of the inserted data key. The expression will randomly find an insertion position I,i's value range is [0,n-1]. It is important to note that the insertion position is random! is not based on the sequential insertion of one-dimensional arrays, which is determined by the characteristics of the HASHMAP data structure. Because the first data is inserted, the randomly found position "i=3" is a null value, so a node object is inserted directly at that location. This insert operation is complete and returns a null value.

2. When inserting the second data, a random insertion position "I=1" is found, and the object at that location is a null value, indicating that no data has been stored and inserting a node object directly at that location. This insert operation is complete and returns a null value.

3. When inserting the third data, the insertion position "I=1" is randomly found, and the data is stored, and the key to insert the data is not the same as the key of the node object at that location (key is the same condition: first must hashcode the same value, And they refer to the same object or they are equal by comparison with the Equals () method, you need to save the newly inserted data to the next property of the node object in that location (it looks like it is linked to the end of the node object in that location). This insert operation is complete and returns a null value.

4. When inserting the fourth data, the insertion position "I=1" is randomly found and the data is stored, and the key to insert the data is the same as the key of the node object at that location, and the value of the node object is replaced with the value of the newly inserted data. The insert operation is complete, returning the value before the node object in the position.

The above example describes the principle of hashmap inserting data, in fact, in addition to the core operations described above, before the return value needs to determine whether the current capacity of HashMap can store more inserted data, depending on the judgment may be expanded, as shown in the following code:

if (++size > threshold)    resize();
Summarize

1. First make clear the fact that HashMap internally actually holds the data in a one-dimensional array, but the stored element type supports the list structure. So, the HashMap after storing the data looks like a "two-dimensional array" ( Note: not really a two-dimensional array).

2. Determine if the HashMap storage object key is the same, the method is as follows:

    • The hashcode value of the newly inserted key must be equal to the hashcode value of the existing object key, which is the precondition
    • The new Insert key refers to the same object as the existing object key, or they are equal when compared by the Equals () method

3.HashMap a one-dimensional array named "table" may have "in-memory" data, because the location of the inserted data is calculated from an expression i = (n - 1) & hash , which can be thought of as a random value.

4. Finally, it is a cliché to emphasize that hashmap is not thread-safe, and that the container used to hold the data inside is essentially a one-dimensional array that is not thread-safe in itself, and that HashMap is not thread-synchronized during the write operation. If you need to use thread-safe hashmap, you should use Concurrenthashmap, because the array in which the data is stored is thread-safe:

/** * The array of bins. Lazily initialized upon first insertion. * Size is always a power of two. Accessed directly by iterators. */// ConcurrentHashMap内部存储数据的table通过关键字volatile修饰,因此是线程安全的transientvolatile Node<K,V>[] table;

The HashMap principle of the Java series

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.