Java and java Official Website

Source: Internet
Author: User

Java and java Official Website

If you are interested, study the source code of HashMap and write down your understanding based on jdk1.8.

This article roughly analyzes the put (), get (), and resize () Methods of HashMap.

 

First, let's take a look at the put () method.

    public V put(K key, V value) {        return putVal(hash(key), key, value, false, true);    }
    /**     * Implements Map.put and related methods     *     * @param hash hash for key     * @param key the key     * @param value the value to put     * @param onlyIfAbsent if true, don't change existing value     * @param evict if false, the table is in creation mode.     * @return previous value, or null if none     */    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,                   boolean evict) {        Node<K,V>[] tab; Node<K,V> p; int n, i;        if ((tab = table) == null || (n = tab.length) == 0)            n = (tab = resize()).length;        if ((p = tab[i = (n - 1) & hash]) == null)            tab[i] = newNode(hash, key, value, null);        else {            Node<K,V> e; K k;            if (p.hash == hash &&                ((k = p.key) == key || (key != null && key.equals(k))))                e = p;            else if (p instanceof TreeNode)                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);            else {                for (int binCount = 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 key                V oldValue = e.value;                if (!onlyIfAbsent || oldValue == null)                    e.value = value;                afterNodeAccess(e);                return oldValue;            }        }        ++modCount;        if (++size > threshold)            resize();        afterNodeInsertion(evict);        return null;    }

 

1. Calculate the hash value of the key through hash (key ).

putVal(hash(key), key, value, false, true)

2. Because hashMap actually stores the table array, you must first determine whether the table array has been initialized. If not, call the resize () method to initialize the table.

if ((tab = table) == null || (n = tab.length) == 0)            n = (tab = resize()).length;

3. The index of the array is obtained through hash and (n-1), and the root table [Index] determines whether it is null. If it is null, it is directly stored in this location.

if ((p = tab[i = (n - 1) & hash]) == null)            tab[i] = newNode(hash, key, value, null);

4. If the table [Index] is not null, it indicates that the position has crashed and the judgment must be continued.

5. If you determine the position p. key = key & p. hash = hash on table [Index], the value is replaced, that is, the key is unique.

6. If the condition 5 is not met, the table [Index] position p is a binary tree, And the TreeNode. putTreeVal () is called to insert the Binary Tree node.

else if (p instanceof TreeNode)                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);

7. If the 5 or 6 conditions are not met, the node will be inserted using the linked list: loop to find p. next until a position is found to be null.

                for (int binCount = 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;                }

8. In Step 5, 6, and 7, if p. key = key & p. hash = hash is found, the value is replaced and the oldValue is replaced with newValue.

            if (e != null) { // existing mapping for key                V oldValue = e.value;                if (!onlyIfAbsent || oldValue == null)                    e.value = value;                afterNodeAccess(e);                return oldValue;            }

9. Count + 1 and check whether the number of existing tables is greater than 2/3 of table []. If the number is greater than, use resize () to expand the table.

10. Now the entire put () operation is complete.

 

Let's take a look at the get () method.

    public V get(Object key) {        Node<K,V> e;        return (e = getNode(hash(key), key)) == null ? null : e.value;    }
    /**     * Implements Map.get and related methods     *     * @param hash hash for key     * @param key the key     * @return the node, or null if none     */    final Node<K,V> getNode(int hash, Object key) {        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;        if ((tab = table) != null && (n = tab.length) > 0 &&            (first = tab[(n - 1) & hash]) != null) {            if (first.hash == hash && // always check first node                ((k = first.key) == key || (key != null && key.equals(k))))                return first;            if ((e = first.next) != null) {                if (first instanceof TreeNode)                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);                do {                    if (e.hash == hash &&                        ((k = e.key) == key || (key != null && key.equals(k))))                        return e;                } while ((e = e.next) != null);            }        }        return null;    }

1. First, judge whether table [] is null. Then, use the hash calculation index to determine whether table [Index] is null. If any item is null, return null directly.

2. Check whether the hash and key of the table [Index] are the same as those of the query. If the hash and key are the same, the table [Index] is directly returned.

if (first.hash == hash && // always check first node                ((k = first.key) == key || (key != null && key.equals(k))))                return first;

3. If condition 2 is not met, judge whether the next of table [Index] is null. If it is null, return null.

4. If the next of table [Index] is not empty, determine whether it is a binary tree. If it is a binary tree, use the getTreeNode () method for search.

if (first instanceof TreeNode)                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);

5. If it is not a binary tree, you can use the Linked List directly for search.

        do {                    if (e.hash == hash &&                        ((k = e.key) == key || (key != null && key.equals(k))))                        return e;                } while ((e = e.next) != null);

6. Now the entire get () method is completed.

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.