Java basic hashMap VS ConcurrentHashMap

There are two structures for data storage in Java, one is an array , and the other is a linked list . The former is characterized by continuous space and fast addressing, but there will be a large movement when adding or deleting elements, so the array The characteristic is that the query speed is fast, and the addition and deletion are slow; while the linked list is difficult to address due to the discontinuous space, and the addition and deletion of elements only need to modify the pointer, so the characteristic of the linked list is that the query speed is slow, and the addition and deletion are fast . So is there a data structure to synthesize arrays and linked lists to take advantage of their respective strengths? The answer is a hash table

HashMap is actually an Entry array. The Entry object contains keys and values. Next is also an Entry object, which is used to deal with hash conflicts and form a linked list.

HashMap can accept null keys and values, while Hashtable cannot; HashMap is non-synchronized; HashMap is fast.

When we pass the key and value to the put() method, we first call the hashCode() method on the key, and the returned hashCode is used to find the bucket location to store the Entry object. "The key point here is to point out that HashMap stores key objects and value objects in buckets as Map.Entry.

 

What happens when two objects have the same hashcode?   Because the hashcode is the same, so their bucket positions are the same, a 'collision' happens. Because HashMap uses a linked list to store objects, this Entry (a Map.Entry object containing key-value pairs) will be stored in a linked list.

 

How do you get the value object if both keys have the same hashcode? When we call the get() method, HashMap will use the hashcode of the key object to find the bucket location. After finding the bucket location, it will call the keys.equals() method to find the correct node in the linked list.

What if the size of the HashMap exceeds the capacity defined by the load factor? The defaultload factor size is 0.75, that is, when a map fills 75% of the bucket, like other collection classes (such as ArrayList, etc.), a bucket array that is twice the size of the original HashMap will be created to recreate Resize the map and put the original objects into the new bucket array. This process is called rehashing because it calls the hash method to find the new bucket location.

Do you understand what's wrong with resizing HashMap? When resizing the HashMap, there is indeed a race condition, because if both threads find that the HashMap needs to be resized, they will try to resize at the same time. During the resizing process, the order of elements stored in the linked list will be reversed, because when moving to a new bucket position, HashMap does not place elements at the end of the linked list, but at the head, which is To avoid tail traversing. If a conditional race occurs, it will be an infinite loop. At this time, you can ask the interviewer why it is so strange to use HashMap in a multi-threaded environment.

Why are wrapper classes like String, Interger suitable as keys? Wrapper classes such as String and Interger are suitable as keys of HashMap, and String is the most commonly used. Because String is immutable and final, and the equals() and hashCode () methodshave beenOther wrapper classes also have this feature. Immutability is necessary because in order to calculate the hashCode(), the key value must be prevented from changing, and if the key value returns different hashcodes when put and when obtained, then you will not be able to find the object you want from the HashMap . Immutability also has other advantages such as thread safety . If you can keep the hashCode constant just by declaring a field final, then do so. Because the equals() and hashCode() methods are used to obtain the object, it is very important for the key object to correctly override these two methods. If two unequal objects return different hashcodes, the chance of collision will be smaller, which will improve the performance of HashMap.

Can we use custom objects as keys? Of course you can use any object as a key, as long as it obeys the definition rules of the equals() and hashCode() methods, and it will not change after the object is inserted into the Map. If the custom object is immutable, then it satisfies the condition of being a key, because it cannot be changed after it is created.

Can we use CocurrentHashMap instead of Hashtable? This is another very popular interview question, because more and more people use ConcurrentHashMap. We know that Hashtable is synchronized, but ConcurrentHashMap has better synchronization performance because it only locks part of the map according to the synchronization level. ConcurrentHashMap can of course replace HashTable, but HashTable provides stronger thread safety.

 

HashMap introduces a red-black tree structure in JDK1.8 and later versions. If the number of linked list elements in the bucket is greater than or equal to 8, the linked list is converted into a tree structure; if the number of linked list elements in the bucket is less than or equal to 6, the tree structure is restored into a linked list. Because the average search length of the red-black tree is log(n), when the length is 8, the average search length is 3. If you continue to use the linked list, the average search length is 8/2=4, which is necessary to convert to a tree. If the length of the linked list is less than or equal to 6, 6/2=3, although the speed is also very fast, the time to convert into a tree structure and spanning tree is not too short. There are also options 6 and 8. There is a difference of 7 in the middle, which can effectively prevent the frequent conversion of linked lists and trees. Suppose, if the number of linked lists exceeds 8, the linked list will be converted into a tree structure, and if the number of linked lists is less than 8, the tree structure will be converted into a linked list. If a HashMap keeps inserting and deleting elements, and the number of linked lists hovers around 8, then Tree to linked list and linked list to tree will frequently occur, and the efficiency will be very low.

One of the biggest differences is that ConcurrentHashMap is thread-safe, hashMap is not thread-safe

It can be seen from the ConcurrentHashMap code that it introduces a concept of "segment lock", which can be understood as splitting a large Map into N small HashTables, and according to key.hashCode() to decide to put the key in the Which HashTable.

In ConcurrentHashMap, when the Map is divided into N segments, when put and get, it is now calculated according to key.hashCode() into which segment:

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325287061&siteId=291194637