Java set, –HashMap, dispel doubts

3 Map

Last night, I went to the bird’s nest and worshipped 5 more than 40 year old men. Count this time, it is third times, each time has different feelings, experience. Looking forward to the next meeting.

说正题前,先附一张昨晚演唱会的图片!

Java set, --HashMap, dispel doubts

Today, I want to introduce the Map collection in the Java collection framework. In daily work, the use of Map is also very extensive.

Unlike the List collection and the Set collection, which is part of Collection, Map is a separate interface, the same level of interface as Collection.

Importantly, the Map collection provides a different method of element storage that is stored in the form of “key–value”. Where each key maps a value. In the Set collection, the storage of the elements is implemented using the Map feature.

Briefly introduced the next Map collection, and then let me the main implementation of its class HashMap, TreeMap, HashTable detailed description.

Java set, --HashMap, dispel doubts

3.1 Map commonly used methods

Before you make a specific introduction, let’s look at the Map interface itself in order to understand the common points of all implementations.

Public interface Map< K, V> Map key--value {/ / return the number of int (size); / / if Map does not contain any key--value, returns true Boolean isEmpty (); / / if the map contains the specified key Map, Boolean containsKey returns true (Object key); / / if this will be a Map one or more keys mapped to the specified value, it returns true Boolean containsValue (Object value); / / return with the specified key value associated with V get (Object key); / / the specified value associated with the specified key V put (K key, V value); / / delete keys and associated from the value of the Map V remove (Object key); / / will specify all copied to this map void putAll mapping in Map (java.util.Map< extends? K, extends? V> m); / / delete all void CL mapping from Map (ear); / / return key contained in the Map Set Set< K> keySet set; (); / / return value of Collection included in map set. Collection< V> values; / / Set () returns the view mapping contained in the Map. Each element in the Set is a Map.Entry Set< java.util.Map.Entry< K, V> > entrySet; / / () specifies the object and the Map equivalent of Boolean equals (Object o); / / int hashCode returns the hash code for this Map (//Map); set stored in the key--value object in Entry. The Map collection is formed in the array structure of interface Entry< K, V> V (getValue; V) {setValue (V value); Boolean equals (Object o); int (hashCode);}}

3.2 HashMap

HashMap, one of the frequently used collections of our work, is also the most frequently asked set of interviews. Presumably, you must have heard: “come, talk about the realization of HashMap” and so on!

Here’s a detailed introduction:

HashMap based on the hash table, the underlying structure is realized by the array, added to the set of elements in the form of “key–value” stored in the array, the array key–value is packaged into an entity to deal with – which is above the Map interface in Entry.

In HashMap, Entry[] holds a collection of all the pairs, when we need fast storage, access, delete the elements of the set, HashMap will obtain the “key to” position in the array according to the hash algorithm, since the implementation of the corresponding operation method.

At this point, careful friends may ask, since it is based on the hash table implementation, then when the new element appears, the hash value repeated, how to do, how to insert it?

Professionally, the hash values are repeated, which we call hash collisions (or hash collisions). In HashMap, is solved through the list in the form, in the hash repeat value array angle, through the list will be newly inserted elements are arranged in order, of course if the key is the same, then we will insert the value overwrite the original value;

Java set, --HashMap, dispel doubts

As shown above, when producing hash after the conflict, the conflict will generate lists in the corner, and orderly.

HashMap inherits from AbstractMap and implements the Map, Cloneable, and Serializable interfaces.
(1) HashMap inherited from AbstractMap, is implemented in the Map interface definition method, reduce the need for the implementation of the Map interface;
(2) HashMap Map, got all methods defined in the Map interface, which has been a part of AbstractMap;
(3) HashMap Cloneable (clone), the method can achieve cloning function;
(4) HashMap Serializable, said can be serialized to transmission through the serialization, the typical application is the Hessian protocol.

It has the following characteristics:

  • The null key is allowed to be stored, and the null value (only one of the null values exists in the first position of the array)
  • Unordered sets, and the order is changed at any time with the addition of elements (addition order, iteration order)
  • Dynamic expansion (consistent with the ArrayList principle) as the element increases
  • There are no duplicate elements (thanks to the hashCode algorithm and the equals method)
  • Thread insecurity

3.2 HashMap basic operations

Next, let’s look at the common methods of HashMap:

Public static void main (String[] AGRS) {/ / create a HashMap collection: Map< String, String> map = new HashMap< String, String> (System.out.println); (HashMap): +map.size (element size "); / / add elements: map.put (" Hi "," hello "); map.put (" my "," hello "); map.put (" name "," hello "); map.put (" is "," hello "); map.put (" jiaboyan "," hello "); / / 1: get the key Set traversal set for (String) (key:map.keySet) {System.out.println (" map key: +key); System.out.println ("map value": +map.get (key));} / / 2: Set collection Set< iterator traversal; Map.Entry< String, String> > mapSet1 = map.entrySet (Iterator<); Map.Entry< String; String> > iterator = mapSet1.iterator (); While ((iterator.hasNext)) {Map.Entry< String, String> mapEntry = (iterator.next); System.out.println ("map key": mapEntry.getKey (+)); System.out.println ("map value": mapEntry.getValue (+));} / / traverse 3: into Set set, enhanced for Set< Map.Entry< String> > String; mapSet2 = map.entrySet (for); (Map.Entry< String, String> mapEntry: mapSet2) {System.out.println ("map key": mapEntry.getKey (+)); System.out.println ("map value": mapEntry.getValue (+));} / / value String: access to access elements keyValue = map.get key ("jiaboyan"); System.out.println ("HashMap key the value:" + keyValue); / / map does not provide replacement of elements The direct set method, but use the new map.put to complete the update operation ("jiaboyan", "HelloWorld"); System.out.println ("HashMap key the value:" + map.get ("jiaboyan")); / / delete: value = map.remove String elements ("jiaboyan"); System.out.println ("HashMap collection elements were removed the value + value); / / empty all elements: map.clear (//hashMap); it contains a key:boolean isContain = map.containsKey (" hello "); //hashMap is empty: Boolean = map.isEmpty (isEmpty);}

3.4 HashMap source code explained (based on JDK1.7.0_45)

Next, we analyze the HashMap source code.

In the same way, we still have problems to understand the implementation of HashMap!

What about the underlying data structure of 1.HashMap?

2.HashMap how to save data, additions and deletions to change how to achieve?

How does 3.HashMap expand?

4., why the expansion of the size must be 2 integer power, that is, 2 of the N times

  • HashMap member variables

Let’s first see what member variables we have in HashMap: table, DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, and so on;

Of these, table is the array of the underlying preservation elements of the HashMap, which is assigned to an empty array by default by EMPTY_TABLE;

DEFAULT_INITIAL_CAPACITY is the default initialization size of an array in HashMap. In the JDK1.7.0_45 version, when the first put (Xin Zeng) element is created, a new Entry[] array with a capacity of 16 is assigned to the table property;

DEFAULT_LOAD_FACTOR is the key parameter of HashMap expansion. When the number of elements stored in HashMap reaches a certain amount, Entry[] will expand. This number of values is calculated according to DEFAULT_LOAD_FACTOR, mainly array size *DEFAULT_LOAD_FACTOR;

Public class HashMap< K, V> extends AbstractMap< K, V> implements Map< K, V> Cloneable, Serializable, //hashMap {in array size: 1 < < 4=2^4=16 static; final int DEFAULT_INITIAL_CAPACITY = 1 & lt; 4; < //1< < 30 said 1 left 30 a left shift, each multiplied by 2, so is 1*2^30=1073741824. Static final int MAXIMUM_CAPACITY < = 1; < 30; / / default load factor: static final float DEFAULT_LOAD_FACTOR = 0.75f; empty array //HashMap is initialized by default: static final java.util.HashMap.Entry< EMPTY_TABLE, >?? [] = {}; / / save the data array of the underlying HashMap: HashMap is an array of Entry transient java.util.HashMap.Entry< K, V> [] Table = (java.util.HashMap.Entry< K, V> EMPTY_TABLE []); the number of elements in //Hashmap: transient int size; / / threshold: equal to capacity * loadFactory, HashMap can determine the amount of data in int threshold; //loadFactor: the load factor, the default value is 0.75, which determines the bucket filling final float loadFactor; //HashMap; Number of times to be manipulated: transient, int, modCount,}
  • The ultimate realization of HashMap

In HashMap, the storage element is a Entry[] array, and the element in it is the Entry object:

Static class Entry< K, V> implements Map.Entry< K, V> //Entry attribute is HashMap {key final K key; //Entry HashMap value attribute is V value; / / a reference to the next node: one-way linked list structure of java.util.HashMap.Entry< K, V> next; / / the Entry hash: key is hash int hash Entry (int; / / constructor: H, K, K, V, V, java.util.HashMap.Entry< K, V> n) {value = V; next = n; key = k; Hash = h;} public final K getKey (return key) {public}; final V getValue (return) {value}; public final V setValue (V newValue) {V oldValue = value; value = newValue; return oldValue publ;} IC final Boolean equals (Object o) {if (! (o instanceof Map.Entry)) return false; Map.Entry e = (Map.Entry) O; Object K1 = getKey (Object); K2 = (e.getKey); if (K1 = = K2 || (K1! = null & & k1.equals (K2))) {Object V1 = getValue (Object); V2 = (e.getValue); if (V1 = = V2 || (V1! = null & & v1.equals (V2))) return true return false;}}; public final int (hashCode) {return (getKey) Objects.hashCode (Objects.hashCode) ^ (getValue () public final String}); toString (return getKey) {(+) = getValue + (void);} recordAccess (java.util.HashMap< K, V> m) {void} reco RdRemoval (java.util.HashMap< K; V> m) {{}
  • HashMap constructor

Let’s see how the concrete construction of HashMap is achieved

Finally, the public HashMap (int, initialCapacity, float, loadFactor) method is specified and assigned to some member variables. The incoming initial capacity did not change the Entry[] capacity size;

Public class HashMap< K, V> extends AbstractMap< K, V> implements Map< K, V>, Cloneable, Serializable; {/ / construction method: initialization capacity specified load factor public HashMap (int initialCapacity, float loadFactor) {if (initialCapacity < 0) throw new IllegalArgumentException ("Illegal initial capacity:" + initialCapacity); / / initialize the specified capacity is greater than the maximum capacity of the HashMap regulations, which will be set to the maximum capacity of if (initialCapacity; > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; / / not less than 0, to determine whether the value of the parameter float is the digital if (loadFactor < = 0; || Float.isNaN (loadFactor)) throw new IllegalArgumentExce Ption ("Illegal load factor:" + loadFactor); / / load factor assignment: this.loadFactor = loadFactor; / / initial capacity assignment to the critical value of attribute threshold = initialCapacity; / / empty methods: no implementation (init);} / / construction method: the initial capacity of public HashMap (int initialCapacity) {this (initialCapacity, DEFAULT_LOAD_FACTOR); non parametric structure:} / / default initial capacity of 16, 0.75 public HashMap (default load factor (DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR) {this}); public (HashMap Map< extends K, extends?? V> m) {this (Math.max ((int) (m.size) / (DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY). DEFAULT_LOAD_FACT OR); inflateTable (threshold); putAllForCreate (m);}
  • HashMap new elements

For HashMap, the addition of new operations can be an important approach, including the expansion of the most core implementation;

First, look directly at the put (K, key, V, value) method:

Public V put (K key, V value) {/ / if you call the put method (the first call to the put method), or an empty array, then the initialization operation if (table = = EMPTY_TABLE) {/ / initialize the table property of HashMap, capacity size set inflateTable (threshold);} / / if the new key null: if (key = null) is a new method called key / / null: return putForNullKey (value); / / calculate the additional elements of the hash value: int hash = hash (key); / / according to the hash value and the length of the array, calculate the new element which is located in the corner of the array should be: int i = indexFor (hash, table.length); / / determine the calculated angle, whether the same key, can understand the traversal of the corner under the list for (java.util.HashMa P.Entry< K, V> E = table[i]; E = null; e! = e.next) {Object K; / / according to the calculated value of the hash, and the equals method to determine whether the same / = = key: if (e.hash = = hash & & ((k = e.key) || = = key key.equals (k))) {/ /key, is to replace the original key value:V oldValue = e.value; e.value = value; e.recordAccess (this); / / return replacement value: return oldValue modCount++;}}; / / add elements to HashMap: addEntry (hash, key, value, I); return null;}

Key added: in the consistency of the judgment, first through the hash value, and then through the equals (or = =) judgment; why do so much?

Since each object’s hashCode () can be rewritten, since it can be overridden, the same hash value may appear. To say the least, even if you use the default JDK calculation, there is a possibility of repetition. So in the end the hash value, also carried out equals (or = =) judgment;

Since then, the use of the equals () method, why = judgment? (fuck, you most problems, which come so much why?)

To put it plainly, the main reason is to solve the string of reasons to compromise!

For strings, “= =” two variables value itself, which is two objects in memory of the first address. The equals () compares whether the contents contained in the string are identical.

But for non string, “=” and “equals” are used to compare the first object address in the heap memory, which is used to compare if two reference variables refer to the same object.

Now, you see?!!!

Next, let’s explain each of the above methods:

When table is an empty array, the array is initialized:

/ / initialize the Entry array, the default size of 16: private void inflateTable (int toSize) {/ / get the capacity of the array to create the size calculation of toSize greater than or equal to 2 times the power (2 times) int capacity = roundUpToPowerOf2 (toSize); / / calculation of HashMap valve value: threshold = (int) Math.min (capacity * loadFactor, MAXIMUM_CAPACITY + 1); / / create an array of Entry objects, re assigning to table: table = new java.util.HashMap.Entry[capacity]; / / determine whether you need to initialize the hashSeed attribute: initHashSeedAsNeeded (capacity);} / / calculation is greater than or equal to the power of 2 number (2 times) private static int roundUpToPowerOf2 (int number) {/ / number in the case of no more than MAXIMUM_CAPACITY: return number > MAXIMUM_CAPACITY =? MAXIMUM_CAPACITY: / / again to three operations: Integer.highestOneBit (number) core method (> 1) (? Integer.highestOneBit (number - 1) < <: 1; 1);}

Added: Integer.highestOneBit (Num) retains only 1 of the MSB, and the rest is 0;

For example: number=16, (16-1) < < 1=30, and then highestOneBit (30), only retain the highest 1, and the rest is 0. 30 of binary is 11110, the highest 1 is retained, the remainder is 0, and 10000=16;

Why do you have to call highestOneBit () when initializing HashMap’s Entry[] to get a number of N’s? Answer later!!!!

When I introduced the member variables of HashMap, I intentionally pulled down an attribute, which is hashSeed. Now let’s make a statement by introducing initHashSeedAsNeeded () and by the way to hashSeed:

Public class HashMap< K, V> extends AbstractMap< K, V> implements Map< K, V> Cloneable, Serializable, static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT {transient int = Integer.MAX_VALUE; hashSeed = 0; //HashMap: private static internal class Holder {/ / internal class member variables: static final int ALTERNATIVE_HASHING_THRESHOLD; / / static code block: static {/ / get JVM parameters -jdk.map.althashing.threshold, if set, get the value of String; altThreshold = java.security.AccessController. (doPrivileged new sun.security.action.GetPropertyAction ("jdk.map.althashing.threshold")); Int threshold; try {/ / determine whether set the jdk.map.althashing.threshold parameters: if not set, then assign the value of ALTERNATIVE_HASHING_THRESHOLD_DEFAULT to threshold (threshold = null! = altThreshold)? Integer.parseInt (altThreshold): ALTERNATIVE_HASHING_THRESHOLD_DEFAULT; //threshold if -1, jdk.map.althashing.threshold is set to -1 if (threshold = = -1) {threshold = Integer.MAX_VALUE;} if (threshold < 0) {throw new IllegalArgumentException ("value must be positive integer.");}} {catch (IllegalArgumentException failed) Throw new Error ("Illegal value for'jdk.map.althashing.threshold'", failed);} //threshold is assigned to ALTERNATIVE_HASHING_THRESHOLD, usually the value is Integer.MAX_VALUE ALTERNATIVE_HASHING_THRESHOLD = threshold;}} / / to determine whether the hashSeed initialization parameter: final Boolean initHashSeedAsNeeded (int capacity) {/ / hashSeed to determine whether it is equal to 0:boolean currentAltHashing = hashSeed = 0; useAltHashing = Boolean! (sun.misc.VM.isBooted & (capacity); & > Boolean = java.util.HashMap.Holder.ALTERNATIVE_HASHING_THRESHOLD; switching = currentAltHashing) ^ useAltHashing; / / to determine whether the need for hashSeed Fu Values: normally, the value of hashSeed is 0 if (SWITCHING), {hashSeed = useAltHashing, sun.misc.Hashing.randomHashSeed (this): 0;} return switching;}}

Through the analysis of the source code under hashSeed initialization process, as long as there is no single definition of JVM property –jdk.map.althashing.threshold, hashSeed value is 0, the value of ALTERNATIVE_HASHING_THRESHOLD is Integer.MAX_VALUE;

So, what’s the point with hashSeed for 0? We’ll answer later!!!!!!

Continue before put (K, key, V, value) source code analysis:

The new elements of the key null / V putForNullKey words: private (V value) {/ / traversal of the first element of an array, to see if there has been a null key:for (java.util.HashMap.Entry< K, V> E = table[0]; E = null; e! = e.next) {/ / if there will be the original value replace if (e.key = = null) {V oldValue = e.value; e.value = value; e.recordAccess (this); / / return to the original value:return oldValue;}} / / if does not contain null, then add operation: modCount++; / / to the first corner of the array inserted under null key--value:addEntry (0, null, value, 0); return null;},

Continue to look down, addEntry (int hash, K key, V value, int bucketIndex) –key key, value, hash value, the array subscript

Void addEntry (int hash, K key, V value, int bucketIndex) {/ / when size is greater than or equal to the critical value and the new elements belong to the angle of the element is not null (the hash conflict), the expansion of if ((size = > & & threshold) (null! = table[bucketIndex])) {/ / becomes 2 times the original size: resize (2 * table.length); / / to calculate the additional elements of the hash value (here don't understand why re calculated) hash = (null! = key)? Hash (key): 0; / / to calculate the additional elements at the array position (due to the length of the array change, need to re calculate the subscript bucketIndex) = indexFor (hash, table.length);} / / entry object to create an array of Entry: createEntry (hash, key, value, bucketIndex);}

When set with elements is greater than or equal to the critical value and the new elements of the array position is null, the new expansion; the array size is 2 times of the original, re calculation of element key, hash value, and the position of the new array.

So, how do you expand?

HashMap capacity: void / resize (int newCapacity) {/ / the original Entry array assignment to oldTable parameters: java.util.HashMap.Entry[] oldTable = table; / / get the current Entry array length: int oldCapacity = oldTable.length; / / if at this stage, the length of the Entry array = = MAXIMUM_CAPACITY: if (oldCapacity = = MAXIMUM_CAPACITY) {/ / the threshold is set to the maximum value of Integer, and returns the threshold = Integer.MAX_VALUE; / / no expansion operation: return;} / / create a new array of Entry: the capacity is 2 times the size of the existing java.util.HashMap.Entry[] newTable = new java.util.HashMap.Entry[newCapacity]; / / the original Entry elements in an array, add to the new array: tran Sfer (newTable, initHashSeedAsNeeded (newCapacity)); / / new array assignment for the table attribute: table = newTable; / / re calculation of expansion threshold: threshold = (int) Math.min (newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);} / / the original elements are copied to the new array: void transfer (java.util.HashMap.Entry[] newTable, Boolean rehash) {the new array length: int / / newCapacity / / Entry = newTable.length; the original traversal array: for (java.util.HashMap.Entry< K, V> E: table) {/ / determined not to null Entry object []: while (null! = e) {java.util.HashMap.Entry< K, V> next = e.next; / / here again judge hashSeed do you want to initialize: if (rehash) { / / for the Strig type, hashSeed is initialized, you need to call the sun.misc.Hashing.stringHash32 to calculate the hash value of e.hash = null = = e.key? 0: hash (e.key);} / / computational elements in the new array subscript: int i = indexFor (e.hash, newCapacity); e.next = newTable[i]; newTable[i] = E; E = next;}}}

Create a Entry object, createEntry (int hash, K key, V value, int bucketIndex) –key key, value, hash value, the array subscript

Void createEntry (int hash, K key, V value, int bucketIndex) {/ / get the corner under the Entry object: java.util.HashMap.Entry< K, V> E = table[bucketIndex]; / / regardless of the angle whether there are elements that will be inserted into the new position, the original elements set to second. Table[bucketIndex] = new java.util.HashMap.Entry< > (hash, key, value, e); //Map collection length +1 size++;}

The above is the whole process of adding elements to HashMap, and also the core of HashMap.

Next, let’s answer the 2 remaining questions:

First of all, to dispel doubts, hashSeed corresponds to the hash (Object, K) method;

Key / / hash value calculation element: final int hash (Object K) {int h = hashSeed; / / if the String type, and hashSeed is not equal to 0, it will call the sun.misc.Hashing.stringHash32 (hash) if calculation (0! = h & & K instanceof; String) {return (sun.misc.Hashing.stringHash32 (String) k);} / / key calculation hash value hashCode, call the key method: H ^ k.hashCode ^ (H) (H; > > > 20) ^ (H > > > 12); / / after a series of operations, obtained a hash value: return H ^ (H > > > 7) ^ (H > > > 4);}

At this point, you should be aware of the role of hashSeed! If hashSeed is initialized, then the string added to the HashMap will call the sun.misc.Hashing.stringHash32 () method to calculate the hash value.

Next, let’s look at the doubts about the highestOneBit () method:

From the above study, we know that Integer.highestOneBit (number) calculates a 2 power greater than or equal to number, that is, a N 2 digit number. And this number is the initial length of Entry[] in HashMap. But in the later expansion operation, we also expanded the original array length 2 times. So, in any case, the length of Entry[] in HashMap is 2 times N;

At this point, you might ask, “why must it be the 2 N side?”

The following is a new calculation method, in which the angle of array elements should be?

Generally speaking, we usually touch hash values, but in HashMap we use algorithms and operations. This is mainly because the% operation is applied to division, and the efficiency is lower, and the 101010 binary data is directly operated with the operation, and the efficiency is higher. If we don’t believe it, we’ll actually test it:

Public static void test (throws InterruptedException) {Thread.sleep (3000); int hash = 4; int length = 16; long = System.nanoTime (start); for (int x = 0; x< 100000; x++) {int result1 //int = hash%length; result2 = hash& (length-1);} long end = System.nanoTime (-start); System.out.println ("total time:" + end);}

Test results: (NS)

Result1 (Mo Yunsuan):7515748 86737895734321 54262167897104 result2 (and arithmetic):3858877 36564935005590 39321283924576

Well, you should believe it this time!

Before we move on, let’s look back at the implementation of “and arithmetic”:

In binary case: 0 & 0=0 0; & 1=0 1; & 0=0 1; & 1=1

When the length is 2 times N words, some even, so length-1 is odd, and odd number into binary words, the last one is 1 (can test), so that when we hash value and operation time and the result that may be odd, odd it may even (depending on the hash value), the better hash hash conflict situation, there is relatively low, that is less likely to form in the HashMap list;

When length is odd, length-1 is even, and if converted to binary, the last one is 0. According to the above and operational implementation, when the operation is performed with 0, the result is 0, no matter what the hash value is, it can only be even at last. Compared to the above, length is odd, equivalent to waste half of the Entry array space, more prone to hash collisions, forming a list, and thus affect the performance of the entire HashMap.

So, HashMap chooses to set length to the N power of 2, and always is even;

In the calculation of element / / array position, with the operation of
/ / hash value on the general use of length modulo (i.e.
static int division hashing method) indexFor (int h, int length) {
return H (length-1);
&}

  • HashMap find elements

The search method for HashMap is simple compared to the new one. One is to get key as null, and the other is key non null.

By acquiring the corresponding key value: / public V get (Object key) {if (key = = null) / / value:return (getForNullKey) key==null; / / get key to null value K,: java.util.HashMap.Entry< V> entry = getEntry (key); / / return the corresponding value:return null = = null: entry? (entry.getValue);} / / hashMap to obtain key null value private V (getForNullKey) value: no element {//hashmap, returns null:if (size = = 0) {return null;} / / get the Entry array, the angle is 0 Entry (put time if NULL key is stored to the corner for the 0 position) was 0 Entry / / get your object to traverse the entire list, see if there are key null key: the return of the corresponding value: For (java.util.HashMap.Entry< K, V> E = table[0]; E = null; e! = e.next) {if (e.key = = null) return e.value;} / / if there are not, it will return null:return null;} / / by the corresponding key get the Entry object: final java.util.HashMap.Entry< K, V> getEntry (Object key //hashmap) {length 0, returns null:if (size = = 0) {return null;} / / key to obtain the corresponding hash value: if key is null, hash = 0; int = hash (key = null)? 0: hash (key); / / hash value is calculated corresponding to the array subscript. Gets an array of Entry objects in the next corner: belongs to the element list traversal; for (java.util.HashMap.Entry< K, V> E = table[indexFor (hash, table.length); E = null; E = e.ne! XT) {Object K; / / key hash value judgment, and then call the equlas method to determine the hash value may be the same, equals further verification; if (e.hash = = hash & & ((k = e.key) key = || (key! = null & & key.equals (k)))) return E;} / / null: return null did not find the return;}
  • HashMap delete elements

The same method of deleting elements is as simple as finding, primarily removing elements from HashMap’s Entry[] array. If the first element of the array subscript is directly under the list of the second elements to move to the head. If it is not the first element, the next attribute of the previous element of the current element points to the next element of the current element;

/ / remove the elements in the hashMap, through the key:public V remove (Object key) {/ / remove a HashMap array of Entry objects: java.util.HashMap.Entry< K, V> E = removeEntryForKey (key); return (E = = null? Null: e.value);} / / key by removing the array of Entry:final java.util.HashMap.Entry< K, V> removeEntryForKey (Object key) {/ / if the Hashmap collection is 0, it returns null:if (size = = 0) {return null;} / / key calculation hash value: int = hash (key = null)? 0: hash (key); / / hash value is calculated corresponding to the array subscript: int i = indexFor (hash table.length, key); / / get the corresponding Entry object: java.util.HashMap.Entry< K, V> prev = table[i]; / / this object is assigned to e:java.util.HashMap.Ent Ry< K, V> E = prev; / / one-way linked list traversal: while (E! = null) {/ / get the next element of the current element: java.util.HashMap.Entry< K, V> next = e.next; Object K; / / hash value judgment elements and equals method are the same, and the incoming key: if (e.hash = = hash & & ((k = e.key) key = || (key! = null & & key.equals (k)))) {/ / add operand: modCount++; / / reduce the number of elements: size--; / / when the first element of the list, directly to the next to the top of the list head element: if (prev = = e) table[i] = next; else / / the current element under the next element Prev.next = next; / / delete current traverse elements: empty methods, / / will be deleted elements no longer is associated with map, no home for null operations such as e.recordRemoval; (this); return E;} / / not the same, the prev = E; E = next;} return E;}