Defined
Public class Hashmap<k,v> extends abstractmap<k,v> implements Map<k,v>, cloneable, Serializable
Public Abstract class Implements
HASHMAP implements the map interface and inherits the Abstractmap. Where the map interface defines the rules for mapping keys to values, and the Abstractmap class provides a backbone implementation of the map interface to minimize the work required to implement this interface, the Abstractmap class has already implemented the map.
Data Structure
We know that two of the most common structures in Java are arrays and pointer references. In fact, HashMap is a "chain table hash", which is the following data structure:
From what we can see is the HashMap bottom implementation or an array, except that each item of the array is a chain. Where the parameter initialcapacity represents the length of the array. The following is the source code of the HashMap constructor://jdk7 Some of the process methods put when to do, in the read-write analysis will be reflected.
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 code does some variable assignment and parameter initialization, and the early JDK assignment to table is also in the constructor, that is, each time a new HashMap is created, a table array is initialized. The elements of the table array are entry nodes:
Read and write implementations
Publicv put (K key, V value) {//new JDK version, the time to create the array is here. if(Table = =empty_table) {inflatetable (threshold); }//HashMap allowed to put key null data if(Key = =NULL) returnPutfornullkey (value); //calculates the hash value of this key inthash =hash (key); //find this key in the middle of the array based on the hash value inti =indexfor (hash, table.length); //traverse the entry linked list at this subscript for(entry<k,v> e = table[i]; E! =NULL; E =e.next) {Object k; //Overwrite if this key already exists if(E.hash = = Hash && (k = e.key) = = Key | |Key.equals (k))) {V OldValue=E.value; E.value=value; E.recordaccess ( This); returnOldValue; }} Modcount++; //add a new key to this subscriptaddentry (hash, key, value, I); return NULL; } Private voidInflatetable (inttosize) { intCapacity =roundUpToPowerOf2 (tosize); Threshold= (int) Math.min (capacity * Loadfactor, maximum_capacity + 1); //The table name HashMap is stored in the structure of the array-linked list.Table =NewEntry[capacity]; Inithashseedasneeded (capacity); }//The value of key null is always in the position of the array subscript 0 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; }//Calculate hash value Final 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); }//Calculates the subscript of this key in the array by a hash value Static intIndexfor (intHintlength) { //assert integer.bitcount (length) = = 1: "Length must be a non-zero power of 2"; returnH & (length-1); }voidAddEntry (intHash, K key, V value,intBucketindex) {if(Size >= threshold) && (NULL!=Table[bucketindex])) {//expanding arrays, which is more time consumingResize (2 *table.length); Hash= (NULL! = key)? Hash (key): 0; Bucketindex=indexfor (hash, table.length); } createentry (hash, key, value, Bucketindex); } //Create a linked list voidCreateentry (intHash, K key, V value,intBucketindex) {Entry<K,V> e =Table[bucketindex]; //Put the new addition in front of the original, the original is E, now is the New,next point eTable[bucketindex] =NewEntry<> (hash, key, value, E);//Let's say it's new .size++; }
Many ideas in the code use some of the concepts in mathematics, in order to optimize the performance of the data distribution of the average and reasonable guarantee. For example, the size of the array, all with 2 index to play, this aspect is not very understand, do not caught dead.
The following get code does not explain the better understanding.
PublicV get (Object key) {if(Key = =NULL) returnGetfornullkey (); Entry<K,V> entry =getentry (key); return NULL= = entry?NULL: Entry.getvalue (); } 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; }
HashMap Source Code Analysis