a Entryentry is an internal interface in the map interface that implements key-value-to-store key. In HashMap, there are entry implementation classes, called entry. The entry class is simple, it contains key,value, an externally introduced hash, and a reference to the next entry object, which is similar to the note node in the linked list in the data structure secondary school, and the key value pairs in HashMap are actually stored by entry properties and constructors for the entry class:
Final K Key; V value; Entry<K,V> next; int Hash; Entry (int h, K K, v V, entry<k,v>= = = = h;}
two initialization of the HashMap
//HashMap Construction Method PublicHashMap (intInitialcapacity,floatloadfactor) {if(Initialcapacity < 0)Throw NewIllegalArgumentException ("Illegal initial capacity:" +initialcapacity);if(Initialcapacity >maximum_capacity) initialcapacity=maximum_capacity;if(loadfactor <= 0 | |Float.isnan (loadfactor))Throw NewIllegalArgumentException ("Illegal load factor:" +loadfactor); This. Loadfactor =Loadfactor;threshold=initialcapacity;init ();}
This is one of the constructors of HashMap, and other constructors refer to this constructor for initialization. Parameter initialcapacity refers to the initial size of the table array in HashMap, and the parameter loadfactory refers to the ratio of the hashmap to the length of the array (for example: the default value of array length is 16, The default value of Loadfactory is 0.75, and if the key value pairs stored in HashMap are entry more than 12, they will be scaled up to twice times the length of the current array. The constructor does not initialize the array, and it is only possible to determine whether to initialize or expand it within the action method of put.
three table arrayThere is a concept in HashMap called threshold (actual capacity), the actual capacity refers to the number of entry allowed in the HashMap, which is the length of the array table built into the HashMap *load ( Load factor). Its role is to ensure the efficiency of hashmap. The table array is another key to the HASHMAP implementation of key-value pairs, and the key-value-to-save methods Seethe index of the left array is calculated based on the hash value of key, and the different hash values may produce the same index, that is, hash conflict, at this time the chain address method is used to deal with the hash conflict, and all the indexed nodes will form a single linked list;The [Key,value] in is the entry object, and the table array is used to store the entry object.
//initialization of the array:Private voidInflatetable (inttosize) {//Find a power of 2 >= tosizeintCapacity =roundUpToPowerOf2 (tosize); Threshold= (int) Math.min (capacity * Loadfactor, maximum_capacity + 1); Table=Newentry[capacity];inithashseedasneeded (capacity);} Private Static intROUNDUPTOPOWEROF2 (intNumber ) {returnNumber >= maximum_capacity? Maximum_capacity: (number > 1)? Integer.highestonebit ((number-1) << 1): 1;}
the Inflatetable method is called when the array is not initialized in a method such as put, and the input parameter is the initialcapacity of the initial setting. In fact, he would call the RoundUpToPowerOf2 method to return a power of a minimum of 2 greater than the initial capacity (one of the reasons is that it is convenient to get the array position where entry is located).
four Add (Put) method
Publicv put (K key, V value) {if(Table = =empty_table) {inflatetable (threshold);//initializes the table array, and the new HashMap threshold represents the initial capacity}if(Key = =NULL)returnPutfornullkey (value);inthash =hash (key);inti =indexfor (hash, table.length); for(entry<k,v> e = table[i]; E! =NULL; E =e.next) {Object k;if(E.hash = = Hash && (k = e.key) = = Key | |Key.equals (k))) {V OldValue=E.value;e.value=value;e.recordaccess ( This);returnOldValue;}} Modcount++; AddEntry (hash, key, value, I);return NULL;} Privatev Putfornullkey (v value) { for(entry<k,v> e = table[0]; E! =NULL; E =e.next) {if(E.key = =NULL) {V OldValue=E.value;e.value=value;e.recordaccess ( This);returnOldValue;}} Modcount++; AddEntry (0,NULL, value, 0);return NULL;}//hash method, used to return the hash value, implemented by the Hashcode () methodFinal intHash (Object k) {inth =Hashseed;if(0! = h && kinstanceofString) {returnSun.misc.Hashing.stringHash32 ((String) k);} H^=K.hashcode (); H^= (H >>>) ^ (H >>> 12);returnH ^ (H >>> 7) ^ (H >>> 4);} voidAddEntry (intHash, K key, V value,intBucketindex) {if(Size >= threshold) && (NULL!=Table[bucketindex])) {Resize (2 *table.length); hash= (NULL! = key)? Hash (key): 0; Bucketindex=indexfor (hash, table.length);} Createentry (hash, key, value, Bucketindex);} voidCreateentry (intHash, K key, V value,intBucketindex) {Entry<K,V> e =Table[bucketindex];table[bucketindex]=NewEntry<>(hash, key, value, e); Size++;}
In the Put method
1. The array is first judged to be empty, and if empty, it is initialized to an empty set with an initial capacity of 16 and a load factor of 0.75 .2. Next, determine if key is null, and if NULL, use the second method to put a key-value pair. 3. Next, call the hash () method on key to get a hash value, and then process the value (Indexfor method) to get the position in the array. 4. Next to the list of the array position, if the hash value of the key at that location is the same as the hash value of the passed key and (the key memory address is equal or equal to the Equals method), indicating that the key value pair is already in the HashMap, the value in the linked list is updated. and returns the old value value. 5. If none of the above methods are working, proceed to the following addentry to create a new entry object to add the incoming key value. In general, the hash value is the same words will find this hash position on the list of the various objects in contrast, if the same will replace the value on the list location, if the hash value is not the same, create a new hash position table In the Putfornullkey method, we see that it is specifically set for a null value, and the hash of the null value is always 0, so the entry object with the key null must be in the No. 0 position of the array. Similarly, if the update is found, it is added if it is not found. calling the AddEntry method means adding a entry to the list of arrays, so you can start by judging whether the number of entry that already exists exceeds the actual amount of capacity. If it is exceeded, the resize method is called to enlarge the array by twice times, noting that the entry that have been deposited will be re-ranked after the expansion because the Indexfor method is related to the length of the array when it was deposited. A fourth method is then called. The Createentry method is simple, which is to put the new entry into the array after placing the linked list head that was originally stored in the array into the new entry. From here we can see that HASHMAP does not guarantee the order problem. The get method and the contains method are consistent with the Put method, i.e. the position of the linked header in the array whose value is located by the hash of the key, and then the Equals method to determine whether the value exists.
Five Delete method (remove)
PublicV Remove (Object key) {Entry<K,V> e =Removeentryforkey (key);return(E = =NULL?NULL: E.value);} FinalEntry<k,v>Removeentryforkey (Object key) {if(Size = = 0) {return NULL;}inthash = (Key = =NULL) ? 0: Hash (key);inti =indexfor (hash, table.length); Entry<K,V> prev =Table[i]; Entry<K,V> e =prev; while(E! =NULL) {Entry<K,V> next =E.next;object K;if(E.hash = = Hash && (k = e.key) = = Key | | (Key! =NULL&&Key.equals (k)))) {Modcount++; Size--;if(prev = =e) table[i]=Next;ElsePrev.next=Next;e.recordremoval ( This);returne;} Prev=e;e=next;}returne;}
Analysis:
, the column is stored in a different hash value corresponding to the location, the entire column is represented by table, table (hash value) represents the element of the first position of the list, adding the value to find in the location of Entry3, then:First step: Table (i) =prev=e=entry0, and then determine whether the hash value and the key object is equal, the first step is not equal, then the execution: prev = E;e = Next; therefore: prep=table (i) =entry0,e=entry1 The second step: Determine whether the hash value and key objects are equal, the second step is still unequal, then execute: prev = E;e = next; So when: Prep=entry1,e=entry2step three: And so on, continue hash value and key object is equal, to the third time Prep=entry2,e=entry3Fourth step: fourth judgment when E.key==key && key.equals (k) satisfies the condition and then judges prev = = E, this judgment is mainly to determine whether the first element, because the first element words two values equal, Just turn the next pointer into table (i) toPrev.next = Next is not perp!=e here, Perp.next normal should be equal to Entry3, now execute Prev.next = Next (e.next= Entry4) Prep.next points to the Entry4, indicating that Entry3 no pointer to it, will be automatically reclaimed by GC garbage collector, to achieve the deletion effect
six query (get) method
PublicV get (Object key) {if(Key = =NULL)returnGetfornullkey (); Entry<K,V> entry =getentry (key);return NULL= = entry?NULL: Entry.getvalue ();} PrivateV Getfornullkey () {if(Size = = 0) {return NULL;} for(entry<k,v> e = table[0]; E! =NULL; E =e.next) {if(E.key = =NULL)returnE.value;}return NULL;} FinalEntry<k,v>getentry (Object key) {if(Size = = 0) {return NULL;}inthash = (Key = =NULL) ? 0: Hash (key); for(entry<k,v> e = table[indexfor (hash, table.length)];e! =NULL; e =e.next) {Object k;if(E.hash = = Hash && (k = e.key) = = Key | | (Key! =NULL&&key.equals (k) )))returne;}return NULL;}
Summary: The query call get when the hash value in the same position to traverse the linked list, compared to the key of each linked list, with the = = or the Equals method to find key the same object out, when the list of the next method returned to null when the link table to the end of the list, Here null means that the entry object is not taken to the end of the list, not the value of the key value pair is Null,value is stored in the value of the entry object HashMap There is no modified method, insert will replace the original value directly
Summarythe size of the final array initialization will be greater than or equal to the power of the smallest 2 of your incoming initial capacity. The reason that key is null or value NULL can be stored in HashMap is due to a separate operation on the null value. In the list of tables in the table array, the common denominator for each entry is the same as the hash (key.hashcode) portion of key. Note the hashcode of key and the override of the Equals method if you want to have two keys map an object, because the criteria for determining the equality of keys are (hashcode equals + (equal to equals)). The first key-value pairs are placed at the end of the list. When the array does not have a linked list, HashMap performance is best for O (1). And the worst is O (threshould).
HashMap Source Code Analysis