Analysis of hashMap (hash table)

We often use data structures, arrays and linked lists of basic types, each with its own advantages. Array: The insertion time complexity is high, while the search time complexity is low. As for the linked list, the opposite is true. In general, the data structure is determined based on how much lookup and insertion are used. However, if you are given a string and count the number of occurrences of each character, you will find that there are some problems. In this case, we can use hashMap (hash table) .

1. Principle:

We combine the advantages of the array and the linked list, use the array when looking for the storage location, and use the linked list when storing it, so as to greatly reduce the time complexity.

1. Create a linked list linkList:

The linked list here is actually almost the same as our previous one-way linked list, but the difference lies in the attributes in the linked list, the built-in hash value, and the built-in generic <K, V> (key value).

public class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

hash: Hash function, which is converted into a fixed-length output by a hash algorithm , and the output is the hash value

The special thing is that the hash value is almost unique and can be used as an int value of the key, and this pair will have a huge effect in the future ^_^.

2. Create a linked list array linkListArr;

This need not go into details, the operation is extremely simple, but remember to initialize the linked list when creating the array.

3. How to use:

getHash (get hash value) : .hashCode()

put (placement): here we can reflect the superiority of hashMap, because our Key value is of any type, so we use it to get the hash value of the key through the getHash() method, and then compare it with the length of the linked list array The AND operation is guaranteed not to exceed the array length

 int storeIndex = getHash(key) & len - 1 ;

In this way, we can easily get the storage location, but there is a problem left, what if we have the same storage subscript after calculation?

At this time, the advantages of the linked list are reflected, and it can be easily added to the end of the linked list. The use of the two greatly improves the efficiency.

get (obtain):  According to the idea in put(), we can also simply deduce it, use the key to calculate the storage subscript, and search one by one in the corresponding table below.

Java source code writing: (belongs to the most important part of hashMap, maximizing efficiency):

 final Node<K,V> getNode(int hash, Object key) {//查找节点,需要hash 和 key 一起,提高效率
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {//table 为链表数组 得到需要的存储下标
            if (first.hash == hash && // 总是想核对头节点
                ((k = first.key) == key || (key != null && key.equals(k))))//只有在hash值相等情况下,才会去判断key是否相等(先比较地址是否相同,不相同后才比较值),以提高效率(因为hash值相等概率极小,而且比较两个int数据快得多)
                return first;
            if ((e = first.next) != null) {//安全性检验,查看后面是否右节点
                if (first instanceof TreeNode)//由于相同的key值过多,链表显得过于冗长,所以源代码中会将链表变成一棵“树”,方便查找
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key)//树内查找方式;
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);//不断循环查找
            }
        }
        return null;
    }

Guess you like

Origin blog.csdn.net/AkinanCZ/article/details/127560365