I. Overview of HASHMAP
HashMap
is one of the most commonly used collection class frameworks in Java and is a very typical data structure in the Java language.
The HashMap is implemented on a hash table-based map interface, which provides all the optional mapping operations. Stored is the
theA mapping that allows multiple null values and a null key. However, this class does not guarantee the order of the mappings, especially because it does not guarantee that the order is constant.
Except HashMap is
Non-synchronousAnd
allow null to be used, the HashMap class is roughly the same as the Hashtable.
This implementation assumes that the hash function distributes elements appropriately between buckets, providing stable performance for basic operations (get and put). The time required to iterate the collection view is proportional to the capacity of the HashMap instance (the number of buckets) and its size (number of key-value mappings). Therefore, if iteration performance is important, do not set the initial capacity too high (or set the load factor too low).
An instance of HashMap has two parameters that affect its performance:
Initial capacityAnd
load Factor。
capacityis the number of buckets in the hash table, the initial capacity is just the capacity at the time of creation of the Hashtable.
a load factor is a scale in which a hash table can reach a full extent before its capacity increases automatically。 When the number of entries in the hash table exceeds the product of the load factor to the current capacity, the Hashtable is
RehashOperations (that is, rebuilding internal data structures), so that the hash table will have about twice times the number of buckets.
Usually
default load Factor (0.75)Seek a compromise on time and space costs. The high load factor, while reducing the space overhead, also increases the query cost (which is reflected in the operations of most HASHMAP classes, including get and put operations). When setting the initial capacity, you should take into account the number of entries required in the mapping and their loading factors to minimize the number of rehash operations. The rehash operation does not occur if the initial capacity is greater than the maximum number of entries divided by the load factor.
Note that this implementation
not synchronousOf If more than one thread accesses a HashMap instance at the same time, and at least one of the threads modifies the list from the structure, it must remain externally synchronized. This is usually done by synchronizing the objects that are used to encapsulate the list. However, if no such object exists, you should use {@link Collections#synchronizedmap collections.synchronizedmap} for "wrapping," which is best done at creation time, To avoid unintended non-synchronous operation of the mappings.
Map m = collections.synchronizedmap (new HashMap (...)); |
Second, the constructor HashMap provides three constructors:
HashMap (): Constructs an empty HashMap with the default initial capacity (16) and the default load factor (0.75).
HashMap (int initialcapacity): Constructs an empty HashMap with the specified initial capacity and default load factor (0.75).
HashMap (int initialcapacity, float loadfactor): Constructs an empty HashMap with the specified initial capacity and load factor.
Two parameters are mentioned here:
Initial capacity,
load Factor。 These two parameters are important parameters that affect the performance of the HashMap, where capacity represents the number of buckets in the hash table, the initial capacity is the capacity to create a hashtable, and the load factor is the size of the hash table before its capacity is automatically increased by a scale, which measures how much space is used for a hash list, The larger the load factor, the higher the filling of the hash table, and the smaller the inverse. For a hash table using the list method, the average time to find an element is O (1+a), so if the load factor is larger, the use of space is more adequate, but the result is a reduction of the search efficiency, if the load factor is too small, then the hash table data will be too sparse, the space caused a serious waste. The system default load factor is 0.75, and we don't need to modify it in general.
HashMap is a data structure that supports fast access, and it is important to understand its data structure in order to understand its performance.
Third, data structure we know that the two most commonly used structures in Java are arrays and analog pointers (references), and almost all data structures can be combined using both, HashMap. In fact, HashMap is a "chain table hash", which is the following data structure:
Entry is a unidirectional linked list. It is a linked list of "HashMap chain-store Method". Implements the Map.entry interface, i.e. Getkey (), GetValue (), SetValue (V value), Equals (Object O), hashcode () These functions Static ClassEntryImplementsMap.entry { FinalK key; V value; Point to next node Entry Next; Final intHash
constructor function Input parameters include "hash value (h)", "key (k)", "Value (v)", "Next node (n)" Entry (intH, K K, v V, Entry N) { Value = V; Next = n; key = k; hash = h; }
Public FinalK GetKey () { returnKey } Public FinalV GetValue () { returnValue } Public FinalV SetValue (v newvalue) { V OldValue = value; value = newvalue; returnOldValue; } Determine if two entry are equal Returns true if the "key" and "value" of the two entry are equal. Otherwise, returns false Public Final BooleanEquals (Object o) { if(! (OinstanceofMap.entry)) return False; 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; } Implement Hashcode () Public Final intHashcode () { return(key==NULL? 0:key.hashcode ()) ^ (value==NULL? 0:value.hashcode ()); } Public FinalString toString () { returnGetKey () + "=" + GetValue (); } When an element is added to HashMap, the draw calls Recordaccess (). There's no processing here. voidRecordaccess (HashMap m) { } When an element is removed from HashMap, the draw calls Recordremoval (). There's no processing here. voidRecordremoval (HashMapm) { } } |
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 for the HashMap constructor:
Find the power of the smallest 2 "greater than capacity" to keep the hash table's capacity at 2 times The idea of the algorithm: by using logical operations to replace the remainder, there is a rule, that is, when N is 2 (Power of two), then x%n==x& (N-1). static final int tablesizefor (int cap) { int n = cap-1; n |= n >>> 1; >>> unsigned right shift, high fill 0 N |= n >>> 2; A|=b means to place a and b in a bitwise OR then assign a value to a. N |= n >>> 4; N |= n >>> 8; N |= N >>> 16; Return (n < 0)? 1: (n >= maximum_capacity)? Maximum_capacity:n + 1; } Constructs an empty hashmap with the specified initial capacity and load factor Public HashMap (int initialcapacity, float loadfactor) { if (initialcapacity < 0) throw new IllegalArgumentException ("Illegal initial capacity:" + initialcapacity); if (Initialcapacity > Maximum_capacity) initialcapacity = maximum_capacity; if (loadfactor <= 0 | | Float.isnan (Loadfactor)) throw new IllegalArgumentException ("Illegal load factor:" + loadfactor); This.loadfactor = Loadfactor; This.threshold = Tablesizefor (initialcapacity); } Constructs an empty HashMap with the specified initial capacity and default load factor (0.75) Public HashMap (int initialcapacity) { This (initialcapacity, default_load_factor); } Constructs an empty HashMap with the default initial capacity (16) and the default load factor (0.75) Public HashMap () { This.loadfactor = Default_load_factor; All other fields defaulted } Constructs a new HashMap with the same mapping relationship as the specified map, with the same capacity as the specified map, with the load factor being the default 0.75 Public HashMap (Map m) { This.loadfactor = Default_load_factor; Putmapentries (M, false); } |
As can be seen from the source code, each time a new HashMap is created, a table array is initialized. The elements of the table array are entry nodes.
Entry is a unidirectional linked list. It is a linked list of "HashMap chain-store Method". It implements the Map.entry interface, which implements Getkey (), GetValue (), SetValue (V value), Equals (Object O), hashcode () These functions Static ClassEntryImplementsMap.entry { FinalK key; V value; Point to next node Entry Next; Final intHash constructor function. Input parameters include "hash value (h)", "key (k)", "Value (v)", "Next node (n)" Entry (intH, K K, v V, Entry N){ Value = V; Next = n; key = k; hash = h; } ...... } |
Where entry is the inner class of HashMap, it contains key keys, value values, next node next, and the hash value, which is very important, precisely because the entry constitutes the table array of items as a linked list. Shanghai Shang School Java Training Original, there are HashMap and other Java technical articles dedicated, please pay more attention.
The HashMap of the most commonly used collection class framework in Java