HashMap implementation of the bottom is the array + linked list structure implementation, add, delete, get elements are first to calculate the hash value, according to the hash value and table.length to calculate the index is the table array subscript, and then do the corresponding operation.
However, HashMap and Hashtable calculate the hash method is different:
HashMap is the table array length is modeled directly with Key's hashcode, whereas HashMap is a two hash of the hashcode of the key to obtain a better hash value and then modulo the length of the table array.
Implementation of the specific method:
HashMap default initialization creates a entry array with a capacity of 16, a default load factor of 0.75, and a threshold value of 16*0.75;
Public HashMap () { this.loadfactor = default_load_factor; threshold = (int) (default_initial_capacity * default_load_factor); Table = new Entry[default_initial_capacity]; Init (); }
For the Put method:
HashMap special handling of NULL value key, always put to table[0] position
The put procedure calculates the hash and then calculates the index value by the hash and table.length, then puts the key to the Table[index] position, and when the other elements exist in Table[index], the Table[index] Position to form a linked list, the newly added elements are placed in Table[index], the original elements through the entry next link, so as a list to solve the hash conflict problem, when the number of elements reached the critical value (Capactiy*factor), the expansion, is the table array length changed to table.length*2;
For the Get method:
Also, when key is NULL, special processing is performed, and a null-key element is found on the linked list of table[0]
Get is the process of calculating the hash and then calculating the index value by hashing and table.length, then traversing the list on Table[index] until key is found, and then returns
For the Remove method:
The Remove method is similar to put get, computes a hash, calculates index, and then iterates through the lookup, removing the found element from the Table[index] List
For the Resize method:
Resize method is not disclosed in HashMap, this method realizes very important HashMap expansion, the concrete process is: first create a new table with a capacity of table.length*2, modify the critical value, Then the table inside the element to calculate the hash value and use hash and table.length*2 to recalculate the index into the new table, it is necessary to note that the hash of each element is all recalculated index, Instead of simply moving the original table corresponding to the index position element, simply move to the new table location
For the ContainsKey method:
The ContainsKey method is to calculate the hash and then use the hash and table.length to get the index value, traverse the Table[index] element to find if it contains the same value as key
Simple myhashmap:
public class Myhashmap {//default initialization size: private static final int default_initial_capacity = 16; Default load factor 0.75 private static final float default_load_factor = 0.75f; Critical value private int threshold; Number of elements private int size; Expansion times private int resize; Private hashentry[] table; Public Myhashmap () {table = new hashentry[default_initial_capacity]; threshold = (int) (default_initial_capacity * default_load_factor); size = 0; } private int index (Object key) {//calculates the position of key in table based on the hashcode of key and table length return Key.hashcode ()% table . length; The public void put (object key, Object value) {//key is null when special handling is required, and for a simplified implementation, the null value if (key = = null) return is omitted; int index = index (key); Traverse the index position of the entry, if the duplicate key is found to update the value of the corresponding entry, and then return hashentry entry = Table[index]; while (entry! = NULL) {if (Entry.getkey (). Hashcode () = = Key.hashcode () && (entry.getkey () = = Key | | en Try.getkey (). EquaLS (key)) {Entry.setvalue (value); Return } entry = Entry.getnext (); }//If the index position is not entry or the duplicate key is not found, the new key is added to the index position of the table Add (index, key, value); } private void Add (int index, object key, Object value) {//To place the new entry at the index position of table first, if the original value is stored as a list of hash Entry Entry = new Hashentry (key, value, Table[index]); Table[index] = entry; Determine if the size reaches the critical value, if it has been reached, expand the table's Capacicy double if (size++ >= threshold) {Resize (table.length * 2); }} private void resize (int capacity) {if (capacity <= table.length) return; hashentry[] newtable = new Hashentry[capacity]; Traversing the original table, each entry is recalculated hash into newtable for (int i = 0; i < table.length; i++) {Hashentry old = Tabl E[i]; while (old = null) {Hashentry next = Old.getnext (); int index = index (Old.getkey ()); Old.setnext(Newtable[index]); Newtable[index] = old; Old = next; }}//Replace table table with newtable = newtable; Modify the threshold value threshold = (int) (TABLE.LENGTH * default_load_factor); resize++; } public object get (object key) {//Here simplifies processing, ignoring null values if (key = = null) return null; Hashentry entry = Getentry (key); return entry = = null? Null:entry.getValue (); } public hashentry Getentry (Object key) {Hashentry entry = Table[index (key)]; while (entry! = NULL) {if (Entry.getkey (). Hashcode () = = Key.hashcode () && (entry.getkey () = = Key | | en Try.getkey (). Equals (key)) {return entry; } entry = Entry.getnext (); } return null; } public void Remove (Object key) {if (key = = null) return; int index = index (key); Hashentry pre = NULL; Hashentry entry = Table[index]; while (entry! = Null) {if (Entry.getkey (). Hashcode () = = Key.hashcode () && (entry.getkey () = = Key | | Entry.getkey (). Equa LS (key))) {if (pre = = null) Table[index] = Entry.getnext (); Else Pre.setnext (Entry.getnext ()); If successfully found and deleted, modify size size--; Return } pre = entry; Entry = Entry.getnext (); }} public Boolean ContainsKey (Object key) {if (key = = null) return false; return Getentry (key)! = NULL; } public int size () {return this.size; public void Clear () {for (int i = 0; i < table.length; i++) {table[i] = null; } this.size = 0; } @Override Public String toString () {StringBuilder sb = new StringBuilder (); Sb.append (String.Format ("size:%s capacity:%s resize:%s\n\n", size, table.length, resize)); for (Hashentry entry:table) {while (entry! = NULL) { Sb.append (Entry.getkey () + ":" + entry.getvalue () + "\ n"); Entry = Entry.getnext (); }} return sb.tostring (); }}class hashentry {private final Object key; private Object value; Private Hashentry Next; Public Hashentry (Object key, object value, Hashentry next) {This.key = key; This.value = value; This.next = Next; } public Object GetKey () {return key; } public Object GetValue () {return value; } public void SetValue (Object value) {this.value = value; } public Hashentry GetNext () {return next; } public void Setnext (Hashentry next) {This.next = next; }}
The underlying implementation of HASHMAP