Java collection of HashMap source code implementation Analysis ...

Source: Internet
Author: User

 1. Introduction through an essay above we know that the bottom of hashset is implemented by map, so what is map? How is the bottom layer implemented? Here we analyze the source code, to see the specific structure and implementation. The Map collection class is used to store element pairs (called "Keys" and "values"), where each key is mapped to a value. Map.entry is its inner class, which describes the key/value pairs in the map. It should be noted that the map, which allows NULL for a key, also allows null values. Its implementation is mainly HashMap and SortedMap, where SortedMap expands the map to keep the keys in ascending order, below we briefly analyze the implementation of HASHMAP. First, an example of application is given: Package com.test.collections;import java.util.collection;import Java.util.hashmap;import java.util.Map; Import Java.util.set;public class Hashmaptest {/** * @param args */public static void main (string[] args) {//TODO Auto-ge nerated method Stubmap<string,string> map = new hashmap<string,string> () map.put ("A", "a"); Map.put ("D", "D Map.put ("S", "s"), Map.put ("C", "C"), Map.put ("B", "B"), Map.put ("W", "w"); System.out.println (Map.size ()); System.out.println (Map.isempty ()); System.out.println (Map.containskey ("a"));//booleansystem.out.println (Map.containsvalue ("a")); /booleansystem.out.println (Map.get ("A")); System.out.println (Map.Remove ("A")); Map.putall (map); set<string> KeySet = Map.keyset (); collection<string&Gt Values = Map.values ();  set<map.entry<string, string>> Entry = Map.entryset (); Map.clear ();}} 2. The inheritance structure HashMap directly inherits the Abstractmap class, implements the Map<k,v>, cloneable, Serializable interface, in addition to these inheritance and implementation, it also has some important property values. Simply look at: default_initial_capacity: Default initialization capacity (+), maximum_capacity: Maximum allowable capacity (1 <<), Default_load_factor: Default    Load factor (0.75); entry[] Table: stores the specific values.    transient int size: Records the size of the map. Final float loadfactor: Load factor. What does this mean in addition to a entry type in the above attribute? Originally this is the maintenance map key value class, used to store the map's specific value, let us look at its concrete implementation structure: Static class Entry<k,v> implements Map.entry<k,v> {final K Key V value; Entry<k,v> Next; final int hash; /** * Creates new entry.  */Entry (int h, K K, v V, 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; The public final Boolean equals (Object o) {if (!) ( o instanceof map.entry)) returnFalse 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 (key==null? 0:key.hashcode ()) ^ (value==null? 0:value.hashcode ()); Final String toString () {return GetKey () + "=" + GetValue ();}/** * This method was invoked whenever the value in an entr Y is * overwritten by an invocation of put (K,V) for a key k that's already * in the HASHMAP. */void Recordaccess (hashmap<k,v> m) {}/** * This method is invoked whenever the entry are * removed from the table . */void Recordremoval (hashmap<k,v> m) {}} entry<k,v> implements the internal interface Map.entry<k,v>,key in the map interface, The value used to store the key value,, entry<k,v> Next, also points to the pointer to the next node, indicating that the map's storage space is not contiguous and can be dispersed. The hash attribute indicates that the position of the key is calculated based on the hash value. It is important to note that this occurs as an inner class of hashmap. In addition there are internal classes keyset,values, EntrySet, VaLueiterator, Keyiterator, Entryiterator but through the class name can know their specific role. 3. Source Resolution A: constructor public HashMap (int initialcapacity, float loadfactor) {if (Initialcapacity < 0) throw new Illegalargum Entexception ("Illegal initial capacity:" + initialcapacity); if (initialcapacity > maximum_capacity) initialcapacity = maximum_capacity; if (loadfactor <= 0 | | Float.isnan (Loadfactor)) throw new IllegalArgumentException ("Illegal load factor:" + loadfactor); Find a power of 2 >= initialcapacity int capacity = 1; while (capacity < initialcapacity) capacity <<= 1; This.loadfactor = Loadfactor; threshold = (int) (capacity * loadfactor); Table = new Entry[capacity]; Init ();  }public HashMap (int initialcapacity) {This (initialcapacity, default_load_factor);} public HashMap () {this.loadfactor = Default_load_factor; threshold = (int) (default_initial_capacity * default_load_factor); Table = new Entry[default_initial_capacity]; Init (); } public HashMap (map<? extends K,? extends v> m){This (Math.max (int) (M.size ()/Default_load_factor) + 1, default_initial_capacity), default_load_factor); Putallforcreate (m); } void Init () {} private void putallforcreate (map<? extends K,? extends v> m) {for (iterator<? extends Map.ent ry<? Extends K,? Extends v>> i = M.entryset (). iterator (); I.hasnext ();  {map.entry<? extends K,? extends v> e = I.next (); Putforcreate (E.getkey (), E.getvalue ());}} The construction method only needs to explain the first one, the other is to pass some default parameter values and then call the first construction method to implement the specific operation. Focus on the first method of construction. It first determines whether the incoming capacity is legitimate and whether the loading factor is legitimate. If the capacity operation maximum value is to be reset, but if the value passed in is negative, the exception is thrown. Then, according to the product of the capacity and load factor to derive the threshold value and assign to the attribute threshold, and then through  table = new Entry[capacity] Allocation of storage space, completed the construction process. The Init () method is empty and does not know what to do. 2.hash (int  h) static int hash (int h) {//This function ensures that hashcodes, differ only by//constant Mul Tiples at each bit position has a bounded//number of collisions (approximately 8 at default load factor). H ^= (H >>>) ^ (h >>> 12); Return h ^ (H >>> 7) ^ (H >>>4); } determines the position of the key according to the hash value, if passed in null, then the returned hash value is 0, the index value is 0.3.size (), isEmpty () public int size () {return size;}/** * Returns &lt ;tt>true</tt> If this map contains no key-value mappings.  * * @return <tt>true</tt> If this map contains no key-value mappings */public Boolean isEmpty () {return size = = 0; The map size is the value that returns the property value size directly, and whether it is null or empty if size is 0. 4.get (object) public V get (object key) {if (key = = null) return Getfornullkey (), int hash = hash (Key.hashcode ()); for (En Try<k,v> e = table[indexfor (hash, table.length)]; E! = null; E = E.next) {Object k; if (E.hash = = Hash && (k = e.key) = = Key | | key.equals (k)) return e.value;} return null ; } returns the corresponding value according to the key, first to determine whether the key is null, if it is empty, call Getfornullkey () returns a null key corresponding to the value of only one. In fact, it is the first value to return the map because null corresponds to a hash value of 0, the storage location is the first. Then call the hash () method to return the only corresponding hash value, and then loop through the map, if the hash value is found to be equal to return its value directly, if no corresponding value is found to return Null.5.containskey (Object) Public boolean ContainsKey (Object key) {return Getentry (key) = null;} final entry<k,v> Getentry (objeCT key) {int hash = (key = = null)? 0:hash (Key.hashcode ()); for (entry<k,v> e = table[indexfor (hash, table.length )]; E! = null; E = E.next) {Object k; e.hash = = Hash && (k = e.key) = = Key | | (Key! = null && key.equals (k)))) return e; } return null; To determine whether a value is included is to get the value first, and if the obtained value is not empty, the object is present. The method to get the key is implemented according to the Getkey () method. First gets the hash value, then loops through the entry array, returns if it encounters the same key or returns to Null.6.put (k,v) public V put (K key, V value) {if (key = = null) return Putfornul Lkey (value); int hash = hash (Key.hashcode ()); int i = 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); return oldValue;}} modcount++; AddEntry (hash, key, value, I); return null; } void AddEntry (int hash, K key, V value, int bucketindex) {entry<k,v> e = Table[bucketindex]; Table[bucketindex] = New entry<k,v> (hash, key, value, E);if (size++ >= threshold) Resize (2 * table.length); } void Resize (int newcapacity) {entry[] oldtable = table; int oldcapacity = Oldtable.length; if (oldcapacity = = Maximum_c apacity) {threshold = Integer.max_value; return;} entry[] newtable = new Entry[newcapacity]; Transfer (newtable); Table = newtable; threshold = (int) (newcapacity * loadfactor); We use the put (K,v) method to add the object to the map, first to determine if the passed key is null, and if NULL, call the Putfornullkey (value) method to correspond to the value of the null key. If it is not empty, first get the hash value of K, and then loop the map, if the value already exists on the update overwrite value and return the old value, otherwise call addentry (hash, key, value, i), insert the new value. Insert and very simple, new a entry object and then determine the array position to specify the value. 4. Other HASHMAP implementations are not synchronous, which means that it is not thread-safe. Both its key and value can be null. In addition, the mappings in HashMap are not ordered. An instance of HashMap has two parameters that affect its performance: initial capacity and load factor. Capacity is the amount of data in the hash table, and the initial capacity is just the capacity at the time of creation of the Hashtable. A load factor is a scale that a hash table can achieve before its capacity increases automatically. When the number of entries in the hash table exceeds the product of the load factor and the current capacity, then the Hashtable is rehash (that is, rebuilding the internal data structure), so that the Hashtable will have approximately twice times the number.

This address: http://www.yanyulin.info/pages/2014/12/34809084852726.html

please retain the source of this article when reproduced, thank you for your cooperation

Java collection of HashMap source code implementation Analysis ...

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.