Detailed Java 8 HASHMAP implementation principle

Source: Internet
Author: User

HashMap is one of the most commonly used tools in the Java development process, and it is often asked during the interview process, which is analyzed by the author's own understanding and numerous information on the web. The author's local JDK version is a 64-bit 1.8.0_171. The following two articles are recommended for reference:

    • Www.cnblogs.com/little-fly/p/7344285.html
    • Monkeysayhi.github.io/2017/08/26/hashmap Implementation principle
Data


The combination and source code can be seen, HashMap the underlying data structure is a node type array, node type is the inner class of HASHMAP, data structure is linked list.

/** * The table, initialized on first use, and resized as * necessary. When allocated, the length is always a power of. * (We also tolerate length zero in some operations to allow * bootstrapping mechanics that is currently not needed.)  */transient node<k,v>[] table;/** * Basic Hash bin Node, used for most entries. (See below for * TreeNode subclass, and in Linkedhashmap for its Entry subclass.)    */static class Node<k,v> implements map.entry<k,v> {final int hash;    Final K Key;    V value;    Node<k,v> Next;        Node (int hash, K key, V value, node<k,v> next) {This.hash = hash;        This.key = key;        This.value = value;    This.next = Next;    } Public final K GetKey () {return key;}    Public final V GetValue () {return value;}    Public final String toString () {return key + "=" + value;}    Public final int hashcode () {return Objects.hashcode (key) ^ Objects.hashcode (value); } Public Final V SetValue(V newvalue)        {V OldValue = value;        value = newvalue;    return oldValue;        The public final Boolean equals (Object o) {if (o = = this) return true;            if (o instanceof map.entry) {map.entry<?,? > E = (map.entry<?,? >) o; if (Objects.equals (Key, E.getkey ()) && objects.equals (value, E.getvalue ())) return T        Rue    } return false; }}
Initial size

HashMap The default initial size is 16, you can call the HashMap (int initialcapacity) method to customize if there are special cases where custom initialization is required.

/** * The default initial capacity - MUST be a power of two. */static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16/** * Constructs an empty <tt>HashMap</tt> with the specified initial * capacity and the default load factor (0.75). * * @param  initialCapacity the initial capacity. * @throws IllegalArgumentException if the initial capacity is negative. */public HashMap(int initialCapacity) {    this(initialCapacity, DEFAULT_LOAD_FACTOR);}
Load factor

The load factor defaults to 0.75, and when HASHMAP is currently using a capacity greater than the current size * load factor, the auto-scale-up is one-time space, and the following methods can be used to customize if there are special cases where custom initialization is required.

/** * The load factor used when none specified in constructor.  */static final Float default_load_factor = 0.75f;/** * Constructs a empty <tt>HashMap</tt> with the specified Initial * capacity and load factor. * * @param initialcapacity The initial capacity * @param loadfactor the load factor * @throws illegalargumentexcept Ion if the initial capacity is negative * or the load factor is nonpositive */public HashMap (int initialcapacity, Float loadfactor) {if (Initialcapacity < 0) throw new illegalargumentexception ("Illegal initial capacity:"    + initialcapacity);    if (initialcapacity > maximum_capacity) initialcapacity = maximum_capacity; if (loadfactor <= 0 | |                                            Float.isnan (Loadfactor)) throw new IllegalArgumentException ("Illegal load factor:" +    Loadfactor);    This.loadfactor = Loadfactor; This.threshold = Tablesizefor (initialcapacity);} 
Tree-Type valve value

Tree threshold This name is the author according to the literal meaning of his own translation, we look at it, the corresponding parameter is Treeify_threshold, the previous mentioned HASHMAP structure is a node array, and node's data structure is linked list, tree valve value is when the chain table length exceeds this value, Modify the data structure of Node to a red-black tree in order to optimize the lookup time, the default value is 8

/** * The bin count threshold for using a tree rather than list for a * bin.  Bins are converted to trees when adding an element to a * bin with at least this many nodes. The value must be greater * than 2 and should be at least 8 to mesh with assumptions in * tree removal about conversion back to plain bins upon * shrinkage. */static final int TREEIFY_THRESHOLD = 8;
Initialization

HASHMAP provides the following four construction methods for initialization, the first three main differences are to set the above described several parameters, the fourth method is to create HashMap through other MAP implementations.

/** * Constructs an empty <tt>HashMap</tt> with the specified initial * capacity and load factor. * * @param initialcapacity The initial capacity * @param loadfactor the load factor * @throws illegalargumentexcept Ion if the initial capacity is negative * or the load factor is nonpositive */public HashMap (int initialcapacity, Float loadfactor) {if (Initialcapacity < 0) throw new illegalargumentexception ("Illegal initial capacity:"    + initialcapacity);    if (initialcapacity > maximum_capacity) initialcapacity = maximum_capacity; if (loadfactor <= 0 | |                                            Float.isnan (Loadfactor)) throw new IllegalArgumentException ("Illegal load factor:" +    Loadfactor);    This.loadfactor = Loadfactor; This.threshold = Tablesizefor (initialcapacity);} /** * Constructs an empty <tt>HashMap</tt> with the specified initial * capacity and the default LOad factor (0.75). * * @param initialcapacity the initial capacity. * @throws IllegalArgumentException If the initial capacity is negative. */public HashMap (int initialcapacity) {This (initialcapacity, default_load_factor);} /** * Constructs an empty <tt>HashMap</tt> with the default initial capacity * (+) and the default load facto R (0.75). */public HashMap () {this.loadfactor = Default_load_factor;//All other fields defaulted}/** * Constructs a new &LT;TT  >HashMap</tt> with the same mappings as the * specified <tt>map</tt>.  The <tt>HashMap</tt> is created with * default load factor (0.75) and a initial capacity sufficient to * hold The mappings in the specified <tt>map</tt>.  * * @param m the map whose mappings am to being placed in this map * @throws NullPointerException If the specified map is    Null */public HashMap (map<? extends K,? extends v> m) {this.loadfactor = Default_load_factor; Putmapentries (M, FALSE);} 
Set the value of the HASHMAP

The Put method is one of the most used APIs in HashMap, its source code implementation is as follows, through the source we can find its principle is divided into the following two steps:

    • Hash the key, and then the last subscript with the current map to determine its position in the array, it is precisely because of this algorithm, we can know that HashMap elements are unordered.
    • After determining its subscript, if the current position is empty then assign the value directly, if not empty then put to the next node, if the current list and add the length of the element to reach the tree threshold, then convert the linked list to a red-black tree
/** * Associates The specified value with the specified key in this map. * If The map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value was to being associated * @param value value to being associated with the Speci Fied Key * @return The previous value associated with <tt>key</tt>, or * <tt>null</tt> if There is no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>nul L</tt> with <tt>key</tt>.) */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 of the value to Put * @param onlyifabsent if true, don ' t change existing value * @param evict if False, the table was in creation mode. * @return Previous value, or null if none */finalv 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.N                    ext = 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;}
Get the value in HashMap

The Get method is also one of the commonly used APIs in HASHMAP, referring to its source code, the principle and put method is exactly the opposite, divided into the following two parts:

    • Gets the contents of the corresponding subscript in the array according to the hash operation value of key
    • Loop linked list or red-black tree, then match value value until the corresponding value is obtained or NULL is returned
/** * Returns the value to which the specified key was mapped, * or {@code null} If this map contains no mapping for the KE  Y. * * <p>more formally, if this map contains a mapping from a key * {@code k} to a value {@code V} such that {@code (Key==null k==null: * key.equals (k))}, then this method returns {@code V};  otherwise * It returns {@code null}. (There can is at the most one such mapping.) * * <p>a return value of {@code null} does not <i>necessarily</i> * indicate that the map contains no MA Pping for the key; It ' s also * possible that the map explicitly maps the key to {@code null}. * The {@link #containsKey ContainsKey} operation May is used to * distinguish these and cases.    * * @see #put (object, object) */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>) Firs            T). 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;} /** * Calls Find for root node.  */final treenode<k,v> gettreenode (int h, Object K) {return ((parent! = null)? Root (): this). Find (h, K, null);}
Related Article

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

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.