It seems that map inherits from Collection like other Collection classes. In fact, Map and Collection do not have any relationship at the structural level, by viewing the source code, we can find that all map operations are based on key-value pairs, rather than individual elements.
The following uses HashMap as an example to gain an in-depth understanding of the implementation mechanism of Map. In this process, open the jdk source code.
Hash Algorithm
HashMap uses the Hash algorithm. Therefore, it is necessary to understand the Hash algorithm first, and the Hash algorithm is also a Hash algorithm, the hash algorithm is used to convert any value into a fixed length output. The output is the hash value, which is a compression ing, that is, the space of hash values is much smaller than the input value space.
To put it simply, the hash algorithm provides a method to quickly access data. It uses an algorithm to establish a correspondence between a key value and a real value, (Each real value can have only one key value, but one key value can correspond to multiple real values). This allows you to quickly access data in arrays and other fields.
Next we create a HashMap, and then put 12 pairs of key-value into it. The default HashMap array length is 16, and our keys are stored in the lattice of the array respectively, the elements stored under each grid are stored in a linked list.
Public static void main (String [] args) {Map map = new HashMap (); map. put ("What", "chenyz"); map. put ("You", "chenyz"); map. put ("Dont", "chenyz"); map. put ("Know", "chenyz"); map. put ("About", "chenyz"); map. put ("Geo", "chenyz"); map. put ("APIs", "chenyz"); map. put ("Cant", "chenyz"); map. put ("Hurt", "chenyz"); map. put ("you", "chenyz" ); Map. put ("google", "chenyz"); map. put ("map", "chenyz"); map. put ("hello", "chenyz");} when we add a new element, we first use the Hash algorithm to calculate the hashcode of the Hash value of this element, then, we can calculate the grid in which the new element should be stored in the hash table. If an element already exists in this grid, then, add the new elements to the linked list with existing lattice elements.
Run the above program. We make some modifications to the HashMap source code to print the hash value of each key object.
What --> hash value: 8
You --> hash value: 3
Dont --> hash value: 7
Know --> hash value: 13
About --> hash value: 11
Geo --> hash value: 12
APIs --> hash value: 1
Cant --> hash value: 7
Hurt --> hash value: 1
You --> hash value: 10
Google --> hash value: 3
Map --> hash value: 8
Hello --> hash value: 0
The calculated Hash values indicate that the key should be stored in the lattice of the corresponding number in the Hash table. If an element already exists in the lattice, the key will be placed in the lattice in the form of a linked list.
From the table above, we can see that the Hash table is the synthesis of the linear table and the linked list. According to the definition of the data structure, we can draw a rough conclusion that the access speed of the Hash algorithm is worse than that of the array, however, compared with a simple linked list, it requires a lot of searching and access.
If you want to find an element in the same way, use the Hash function to calculate the hashcode of this element, and then use this hashcode value, directly find the linear lattice corresponding to the hash value. after entering the grid, compare the elements of the linked list stored in the grid one by one until the corresponding hash value is found.
After a brief understanding of the Hash algorithm, we open the HashMap source code.
Initialize HashMap
Next let's take a look at Map map = new HashMap (); what the code has done and what changes have taken place in the data structure.
Several important attributes in HashMap
Transient Entry [] table;
The Entry array of the object used to save key-value, that is, the Hash table.
Transient int size;
Returns the number of key-value pairs of HashMap.
Final float loadFactor;
Load factor used to determine whether the Entry array is resized. The default value of HashMap is 0.75f.
Int threshold;
Reconstruction factor, (capacity * load factor) multiplication value of the load factor and Entry [] array volume
Public class HashMap <K, V> extends AbstractMap <K, V> implements Map <K, V>, Cloneable, Serializable {int threshold; final float loadFactor; transient Entry [] table; static final float DEFAULT_LOAD_FACTOR = 0.75f; static final int partition = 16; public HashMap (int initialCapacity, float loadFactor) {if (initialCapacity <0) throw new partition ("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 () ;}use public HashMap (int initialCapacity, float loadFactor) for example, the other two constructors construct HashMap in the same way.
First, determine the initialization length of the hashMap. Here, we use a loop to find a number that is greater than 2 of initialCapacity. For example, the value of initialCapacity is 10, so the number greater than 10 is the 4 power of 2, that is, 16
The value of capacity is given 16, so the actual length of the table array is 16. This policy is used to construct the length of the Hash table, it is because the power operation of 2 is quite efficient for computers.
LoadFactor,