Source code analysis: the difference between hashmap and hashtable

Source code analysis The difference between HashMap and HashHashTable

This question has a very high hit rate in interviews. Today I will talk to you about the differences between the two.

1. Inherit from different parent classes

Insert image description here
Insert image description here

Looking at the source code, we can see that the parent class inherited by HashTable is Dictionary (the meaning of dictionary), and the parent class inherited by HashMap is AbstractMap class. But the interfaces implemented by both are the same.

2. Thread safety issues

HashTable is thread-safe, HashMap is thread-unsafe.

Every method in the HashTable class has been added synchronized. Although HashMap is not thread-safe, its efficiency is much better than HashTable. If it is a single-threaded operation, HashMap frees up this part of the operation. When multi-threaded operations are required, the thread-safe ConcurrentHashMap can be used. Although ConcurrentHashMap is also thread-safe, its efficiency is many times higher than Hashtable. Because ConcurrentHashMap uses segmentation locks, it does not lock the entire data.

3. The key is null is handled differently.

/** HashTable source code **/


/**
     * Maps the specified <code>key</code> to the specified
     * <code>value</code> in this hashtable. Neither the key nor the
     * value can be <code>null</code>. <p>
     *
     * The value can be retrieved by calling the <code>get</code> method
     * with a key that is equal to the original key.
     *
     * @param      key     the hashtable key
     * @param      value   the value
     * @return     the previous value of the specified key in this hashtable,
     *             or <code>null</code> if it did not have one
     * @exception  NullPointerException  if the key or value is
     *               <code>null</code>
     * @see     Object#equals(Object)
     * @see     #get(Object)
     */
    public synchronized V put(K key, V value) {
    
    
        // Make sure the value is not null
        if (value == null) {
    
    
            throw new NullPointerException();
        }

The comments of the put() method of HashTable have already explained in detail: when your key or value is null, a null pointer exception will be thrown.

/** HashMap source code **/

  /**
     * Computes key.hashCode() and spreads (XORs) higher bits of hash
     * to lower.  Because the table uses power-of-two masking, sets of
     * hashes that vary only in bits above the current mask will
     * always collide. (Among known examples are sets of Float keys
     * holding consecutive whole numbers in small tables.)  So we
     * apply a transform that spreads the impact of higher bits
     * downward. There is a tradeoff between speed, utility, and
     * quality of bit-spreading. Because many common sets of hashes
     * are already reasonably distributed (so don't benefit from
     * spreading), and because we use trees to handle large sets of
     * collisions in bins, we just XOR some shifted bits in the
     * cheapest possible way to reduce systematic lossage, as well as
     * to incorporate impact of the highest bits that would otherwise
     * never be used in index calculations because of table bounds.
     */
    static final int hash(Object key) {
    
    
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

The put() method of HashMap returns a detailed description in the body: when the key is null, the key value will be equal to 0 for hashcode calculation.

4. Different initial capacities

The initial capacity of HashMap is 16. Every time a map is created, the initial size is started when a value is put into the map. The initial capacity of HashTable is 11, and this capacity will be initialized every time it is new.

5. Expansion capacity is different in size

The expansion capacity of HashMap is 2 times of the original capacity, and the expansion capacity of HashTable is 2n+1 times of the original capacity.

The focus of Hashtable is to make hash results more uniform and reduce hash conflicts. When the size of the hash table is a prime number, the results of a simple modulo hash will be more uniform. HashMap pays more attention to the calculation efficiency of hash. During modulo calculation, if the modulus is a power of 2, then we can directly use bit operations to get the result, which is much more efficient than division. In order to speed up hashing, HashMap fixes the size of the hash table to a power of 2. Of course, this introduced the problem of uneven hash distribution, so HashMap made some changes to the hash algorithm to solve this problem. This results in different methods of calculating hash values ​​between Hashtable and HashMap.

6. The methods of calculating hash values ​​are also different.

/** HashTable source code **/

Insert image description here

Hashtable directly uses the hashCode of the object itself. HashCode is an int type value calculated by JDK based on the object's address, string, or number. hash & 0x7FFFFFFFF is to change the hash value to a positive number, and then use division to leave the remainder to obtain the final position and map it to the hash table. Hashtable needs to perform a division operation when calculating the position of elements, and the division operation is time-consuming.

/** HashMap source code **/

Insert image description here

'>>>' is an unsigned right shift operation, and the high bits are filled with 0.

First determine whether the key is equal to null. If it is equal to null, 0 will be returned as the hash value. Otherwise, the operation (h=key.hashCode()) ^ (h >>> 16) is performed, and the result of the XOR of the high and low bits of the hash value of the key is used as the low bit and remains unchanged.

First determine whether the key is equal to null. If it is equal to null, 0 will be returned as the hash value. Otherwise, the operation (h=key.hashCode()) ^ (h >>> 16) is performed, and the result of the XOR of the high and low bits of the hash value of the key is used as the low bit and remains unchanged.

Guess you like

Origin blog.csdn.net/weixin_47294072/article/details/107550919