HashMap与HashTable

来源:互联网 发布:如何成为网络写手游戏 编辑:程序博客网 时间:2024/06/04 19:55

A.HashMap不加synchronized,Hashtable加synchronized

B.HashMap允许Key和Value为null,而Hashtable不允许

C.由于synchronized原因,HashMap效率比Hashtable高,但是Hashtable比HashMap安全

我们来分析一下源码:

1.HashMap

2.HashTable

    /**     * The hash table.     */    private transient HashtableEntry<K, V>[] table;
一个HashtableEntry的数组。

 /**     * Note: technically the methods of this class should synchronize the     * backing map.  However, this would require them to have a reference     * to it, which would cause considerable bloat.  Moreover, the RI     * behaves the same way.     */    private static class HashtableEntry<K, V> implements Entry<K, V> {        final K key;        V value;        final int hash;        HashtableEntry<K, V> next;        HashtableEntry(K key, V value, int hash, HashtableEntry<K, V> next) {            this.key = key;            this.value = value;            this.hash = hash;            this.next = next;        }        public final K getKey() {            return key;        }        public final V getValue() {            return value;        }        public final V setValue(V value) {            if (value == null) {                throw new NullPointerException("value == null");            }            V oldValue = this.value;            this.value = value;            return oldValue;        }        @Override public final boolean equals(Object o) {            if (!(o instanceof Entry)) {                return false;            }            Entry<?, ?> e = (Entry<?, ?>) o;            return key.equals(e.getKey()) && value.equals(e.getValue());        }        @Override public final int hashCode() {            return key.hashCode() ^ value.hashCode();        }        @Override public final String toString() {            return key + "=" + value;        }    }
这个HashtableEntry有个next指针指向下一个结点,看起来像个链表。

    /**     * Constructs a new {@code Hashtable} using the default capacity and load     * factor.     */    @SuppressWarnings("unchecked")    public Hashtable() {        table = (HashtableEntry<K, V>[]) EMPTY_TABLE;        threshold = -1; // Forces first put invocation to replace EMPTY_TABLE    }
构造函数中对链表进行初始化。

    /**     * Associate the specified value with the specified key in this     * {@code Hashtable}. If the key already exists, the old value is replaced.     * The key and value cannot be null.     *     * @param key     *            the key to add.     * @param value     *            the value to add.     * @return the old value associated with the specified key, or {@code null}     *         if the key did not exist.     * @see #elements     * @see #get     * @see #keys     * @see java.lang.Object#equals     */    public synchronized V put(K key, V value) {        if (key == null) {            throw new NullPointerException("key == null");        } else if (value == null) {            throw new NullPointerException("value == null");        }        int hash = Collections.secondaryHash(key);        HashtableEntry<K, V>[] tab = table;        int index = hash & (tab.length - 1);        HashtableEntry<K, V> first = tab[index];        for (HashtableEntry<K, V> e = first; e != null; e = e.next) {            if (e.hash == hash && key.equals(e.key)) {                V oldValue = e.value;                e.value = value;                return oldValue;            }        }        // No entry for key is present; create one        modCount++;        if (size++ > threshold) {            rehash();  // Does nothing!!            tab = doubleCapacity();            index = hash & (tab.length - 1);            first = tab[index];        }        tab[index] = new HashtableEntry<K, V>(key, value, hash, first);        return null;    }
添加数据时加锁。而HashMap是不加锁的。首先通过next指针判断链表中是否已经存在该元素,如果存在,则更新为新的元素。然后如果链表中没有该元素,则添加到链表的某一位置。这个既是数组又是链表的数据结构结合了查找和插入/删除的优点。其中的hash函数需要了解了解。




0 0