If we were to design hashmap ourselves, what should we do? Array. With array storage nodes, each node has key and value information. Well, first we have to have node storage key,value.
Node Design
In this node class, there are three properties, hash value, key, value.
1 classNode<k,v> {2 Final intHash//Hash Value3 FinalK key;//Key4V value;//value5 //constructor Function6Node (intHash, K key, V value, node<k,v>next) {7 This. hash =Hash;8 This. Key =key;9 This. Value =value;Ten This. Next =Next; One } A - Public FinalK GetKey () {returnkey;} - Public FinalV GetValue () {returnvalue;} the Public FinalString toString () {returnKey + "=" +value;} - - Public Final Booleanequals (Object o) { - if(O = = This) + return true; - if(Objects.equals (Key, O.getkey ()) && + objects.equals (value, O.getvalue ())) A return true; at - return false; - } -}
View Code
Note: There is more next in the constructor here, you can ignore it. Strange, add this block of code, how to edit the time can not be deleted. Hey...
initializing an array
Defines an array with a capacity of 100, which is used to store node nodes. Default_initial_capacity, it must be a power of 2, in the JDK provided by the HashMap its value is 1 << 4, that is 16, here directly fill 16 can not? Why do you have to write like this?
1 Static Final intdefault_initial_capacity=100;2 transientNode<k,v>[] table;3 /**4 * Constructor Function5 */6 PublicSimplehashmap ()7 {8Table= (node<k,v>[])Newnode[default_initial_capacity];9}
View CodeIncreased Operation-put
Adding elements to an array with a capacity of 100 is actually simple, as follows:
1) hash The key value to get the hash value.
2) Create node nodes by using the hash value, key, and value obtained above.
3) The corresponding subscript is obtained by hash value and array length.
4) assigns a value to the obtained subscript.
Note: Here the hash function of the key hash call, specifically I do not understand why this design?
1 Static Final int Hash (Object key) {2 int h; 3 return null) ? 0: (H = key.hashcode ()) ^ (H >>> +); 4 }
View Code
In addition, according to the hash value and capacity (array length) to obtain the corresponding subscript, I do not understand why this design?
1 i = (n-1) & Hash
View Code
The specific put code is as follows:
1 Publicv put (K key, v value)2 {3 //Create a new node4Node<k,v> p;intn, I;5 //Get length6n=table.length;7 //hash the key value8 intHash=hash (key);9 //hash conflicts are not considered at this timeTenTable[i = (n-1) & hash]=NewNode (hash,key,value); One //return the original value A returnvalue; - - } the //Create a new node -Node<k,v> NewNode (intHash, K key, V value) { - return NewNode<>(hash, key, value); -}
View Code
Delete Operation-remove
The delete operation is essentially the same as adding, first to get the subscript, and then to assign the value NULL.
1 PublicV Remove (Object key) {2Node<k,v>e;3 return(E = RemoveNode (hash (key), key) = =NULL?4 NULL: E.value; 5 }6 /**7 * Delete nodes. 8 * Conflicts are not currently considered, and when the corresponding subscript has a value and is not NULL, the value is returned and the corresponding value is set to null9 * This is not considered perfect because HashMap allows value to be null, so it does not really delete this element. Ten * @paramHash One * @paramKey A * @return - */ - FinalNode<k,v> RemoveNode (inthash, Object key) { theNode<k,v> p;intindex; -P=table[index = (table.length-1) &Hash]; - if(p!=NULL) - { +table[index]=NULL; - } + returnp; A}
View Code
Query Operation-get
As with the remove and put operations, it is necessary to get the subscript based on the key value, and then return the corresponding value value.
1 /**2 * Based on key value, get value3 * @paramKey4 * @return5 */6 PublicV get (Object key) {7Node<k,v>e;8 return(E = getnode (hash (key), key) = =NULL?NULL: E.value;9 Ten } One /** A * Get the corresponding value - * @paramHash - * @paramKey the * @return - */ - FinalNode<k,v> GetNode (inthash, Object key) { - returntable[(table.length-1) &Hash]; +}
View Code
Whether the element exists--containskey
Depending on the key value, it is the same as the get operation, except that the Boolean value is returned here.
1 /**2 * If there is a key value for3 * @paramKey4 * @return5 */6 Public BooleanContainsKey (Object key) {7 returnGetNode (hash (key), key)! =NULL;8 9}
View Code
Wow! Isn't it simple? Here are two questions, just do not know that the underlying acquisition and hash is worth getting why to design? Is it because it's the best? Is there a much less chance of conflict if the underlying gets this method? Throughout the series, I did not discuss HashMap inheritance Abstractmap to implement the map interface.
Analysis HashMap---HashMap simple implementation of ADD, delete, check.