[JDK1.8 source code reading] Hashtable.class (end)

You need to understand before looking at hashtable

Hashtable本质是一条线性的链表:
0、Hashtable是较早的JDK版本中的类,数据结构是`Entry<K, V> next`单向链表
1、哈希函数(直接寻址法、数字分析法、平方取中法、折叠法、随机数法、除留余数法)
2hashCode()的生成在Object类内置了方法
3、链表Entry<?, ?>[]的数据结构
4、如何插入和删除一个Entry
5、与HashMap的区别

Ancestor Dictionary (inheritance)

Inheriting Dictionary <K, V>, this is an abstract key and value. The interior is all abstract variables.

public abstract
class Dictionary<K,V> {
    public Dictionary() {  }
    abstract public int size();
    abstract public boolean isEmpty();
    abstract public Enumeration<K> keys();
    abstract public Enumeration<V> elements();
    abstract public V get(Object key);
    abstract public V put(K key, V value);
    abstract public V remove(Object key);
}

Brother Map, Cloneable, Serializable (implement interface)

Cloneable and Serializable are both empty interfaces.

  • Map <K, V> interface: general operation method for defining variables
  • Cloneable interface: clone first allocates memory, the allocated memory is the same as the memory of the object calling the clone method, and then fills the value of each variable in the source object into the new object. After the filling is completed, the clone method returns a new address The object of this new address is the same as the source object, but the address is different.
  • Serializable interface: endow serialization capabilities

Child hash, key, value

  • It can be seen from the data structure that Hashtable is a singly linked list composed of Entry <K, V>
private static class Entry<K, V> implements Map.Entry<K, V> {
        final int hash;//使用key的hashCode(),是Object类的native的方法
        final K key;
        V value;
        Entry<K, V> next;
        protected Entry(int hash, K key, V value, Entry<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
  • Meaning of other constant expressions
    private transient Entry<?, ?>[] table;//看1108行的数据结构
    private transient int count;//统计Entry的数量
    private int threshold;//addEntry的时候如果比count小,则调用rehash()增加容量,重新计算每个键值对的hashCode
    private float loadFactor;
    private transient int modCount = 0;
    private static final long serialVersionUID = 1421746759512286392L;
  • table: array of key-value pairs, each Entry is essentially the head of a singly linked list
  • count: the number of entries in the current table, if it exceeds the threshold, it will be expanded, that is, the rehash method is called
  • threshold:rehash阈值
  • loadFactor: load factor
  • modCount: used to implement the "fail-fast" mechanism (that is, fast failure). The so-called fast failure is that in the concurrent collection, when iterating the operation, if there are other threads to modify it structurally, the iterator will immediately sense it and immediately throw a ConcurrentModificationException exception, rather than waiting until the iteration is completed. Tell you (you have made a mistake).
  • serialVersionUID: version serial number, used for serialization

How exactly to insert a value

  • Make sure the key is not in the table, if the value corresponding to the key exists, overwrite the value with the new value
  • If the value corresponding to the key does not exist, add the addEntry method to add to the index position
public synchronized V put(K key, V value) {
        if (value == null) {
            throw new NullPointerException();
            }
        //确保key不在table,如果key对应的值存在,则用新值覆盖value
        Entry<?, ?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K, V> entry = (Entry<K, V>) tab[index];
        for (; entry != null; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }
        // 如果key对应的值不存在,就调用addEntry方法加入
        addEntry(hash, key, value, index);
        return null;
    }
  • tab [index] is different from HashMap, Hashtable chooses to put the newly inserted element to the front of the linked list
private void addEntry(int hash, K key, V value, int index) {
        modCount++;
        Entry<?, ?> tab[] = table;//重新增加一个数组
        if (count >= threshold) {
            rehash();// 当前元素大于等于阈值,就扩容并且再计算hash值
            tab = table;
            hash = key.hashCode();
            //0x7FFFFFFF 0111 1111 1111 1111 1111 1111 1111 1111
            index = (hash & 0x7FFFFFFF) % tab.length;//第一位是0表示正数,0与任何数都是0,1与任何数都是1,因此以此保证第一位是0,其后不变
        }
        @SuppressWarnings("unchecked")
        Entry<K, V> e = (Entry<K, V>) tab[index];// Creates the new entry.
        //和HashMap不同,Hashtable选择把新插入的元素放到链表最前边,而且没有使用红黑树
        tab[index] = new Entry<>(hash, key, value, e);
        count++;
    }

Exactly delete insert a value

  • e is the node to be deleted, traverse the linked list, if the table (e.hash == hash) && e.key.equals(key)indicates that there is the same node, delete it (next point to the next node)
 public synchronized V remove(Object key) {
        Entry<?, ?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K, V> e = (Entry<K, V>) tab[index];//e是要删除的节点
        for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                modCount++;
                if (prev != null) {
                    prev.next = e.next;
                } else {
                    tab[index] = e.next;
                }
                count--;
                V oldValue = e.value;
                e.value = null;
                return oldValue;
            }
        }
        return null;
    }

You should know

Why the key / value of Hashtable cannot be null

Perhaps the designers of the Hashtable class thought that null was useless as a key and value.

Both the key and value values ​​of the HashMap object can be null.
Neither the key nor the value of the HashTable object can be null.

Hashtable was born earlier than HashMap

Hashtable naming does not use the hump rule, HashMap is used. Hashtable is very low in project usage.

Reference: https://blog.csdn.net/u010297957/article/details/51974340

Published 99 original articles · Like 106 · Visit 270,000+

Guess you like

Origin blog.csdn.net/lglglgl/article/details/105145060