Java集合框架:了解Hashtable

Hashtable

基于 数组+链表 实现的线程安全映射

Hashtable继承关系

Hashtable实现了Serializable接口,支持序列化,可通过序列化传输

Hashtable实现了Cloneable接口,覆盖了clone()方法,能被克隆

Hashtable继承了Dictionary抽象类,有映射的基本操作

Hashtable源码分析 

静态 类KeySet:

    private class KeySet extends AbstractSet<K> {
        public Iterator<K> iterator() {
            return getIterator(KEYS);
        }
        public int size() {
            return count;
        }
        public boolean contains(Object o) {
            return containsKey(o);
        }
        public boolean remove(Object o) {
            return Hashtable.this.remove(o) != null;
        }
        public void clear() {
            Hashtable.this.clear();
        }
    }

静态 类EntrySet:

private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
    public Iterator<Map.Entry<K,V>> iterator() {
        return getIterator(ENTRIES);
    }

    public boolean add(Map.Entry<K,V> o) {
        return super.add(o);
    }

    public boolean contains(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
        Object key = entry.getKey();
        Entry<?,?>[] tab = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;   // 得到数组位置的索引

        // 遍历索引处的链表
        for (Entry<?,?> e = tab[index]; e != null; e = e.next)
            if (e.hash==hash && e.equals(entry))
                return true;
        return false;
    }

    public boolean remove(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
        Object key = entry.getKey();
        Entry<?,?>[] tab = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;


        @SuppressWarnings("unchecked")
        Entry<K,V> e = (Entry<K,V>)tab[index];
        for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
            if (e.hash==hash && e.equals(entry)) {
                if (prev != null)
                    // 待删元素e的前一个元素prev的指针指向e的下一个元素next
                    prev.next = e.next;
                else
                    tab[index] = e.next;

                e.value = null; // clear for gc.
                modCount++;
                count--;
                return true;
            }
        }
        return false;
    }

    public int size() {
        return count;
    }

    public void clear() {
        Hashtable.this.clear();
    }
}

私有静态 类Entry:

private static class Entry<K,V> implements Map.Entry<K,V> {
    final int hash;
    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;
    }

    @SuppressWarnings("unchecked")
    protected Object clone() {
        return new Entry<>(hash, key, value,
                              (next==null ? null : (Entry<K,V>) next.clone()));
    }

    // Map.Entry Ops

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }

    public V setValue(V value) {
        if (value == null)
            throw new NullPointerException();

        V oldValue = this.value;
        this.value = value;
        return oldValue;
    }

    public boolean equals(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry<?,?> e = (Map.Entry<?,?>)o;

        return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
           (value==null ? e.getValue()==null : value.equals(e.getValue()));
    }

    public int hashCode() {
        return hash ^ Objects.hashCode(value);
    }

    public String toString() {
        return key.toString()+"="+value.toString();
    }
}

私有 类Enumerator:

private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
    final Entry<?,?>[] table = Hashtable.this.table;
    int index = table.length;
    Entry<?,?> entry;
    Entry<?,?> lastReturned;
    final int type;

    /**
     * 指示此Enumerator作为迭代器还是枚举(true -> Iterator)
     */
    final boolean iterator;

    /**
     * The modCount value that the iterator believes that the backing
     * Hashtable should have.  If this expectation is violated, the iterator
     * has detected concurrent modification.
     */
    protected int expectedModCount = Hashtable.this.modCount; // 修改计数

    Enumerator(int type, boolean iterator) {
        this.type = type;
        this.iterator = iterator;
    }

    public boolean hasMoreElements() {
        Entry<?,?> e = entry;
        int i = index;
        Entry<?,?>[] t = table;
        /* Use locals for faster loop iteration */
        while (e == null && i > 0) {
            e = t[--i];
        }
        entry = e;
        index = i;
        return e != null;
    }

    @SuppressWarnings("unchecked")
    public T nextElement() {
        Entry<?,?> et = entry;
        int i = index;
        Entry<?,?>[] t = table;
        /* Use locals for faster loop iteration */
        while (et == null && i > 0) {
            et = t[--i];
        }
        entry = et;
        index = i;
        if (et != null) {
            Entry<?,?> e = lastReturned = entry;
            entry = e.next;
            return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e);
        }
        throw new NoSuchElementException("Hashtable Enumerator");
    }

    // Iterator methods
    public boolean hasNext() {
        return hasMoreElements();
    }

    public T next() {
        if (Hashtable.this.modCount != expectedModCount)
            throw new ConcurrentModificationException();
        return nextElement();
    }

    // 删除元素
    public void remove() {
        if (!iterator)
            throw new UnsupportedOperationException();
        if (lastReturned == null)
            throw new IllegalStateException("Hashtable Enumerator");
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();

        // 同步
        synchronized(Hashtable.this) {
            Entry<?,?>[] tab = Hashtable.this.table;
            int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length; // 获取条目索引

            @SuppressWarnings("unchecked")
            Entry<K,V> e = (Entry<K,V>)tab[index];
            for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
                // 删除迭代器最后返回的条目
                if (e == lastReturned) {
                    if (prev == null)
                        tab[index] = e.next;
                    else
                        prev.next = e.next;
                    expectedModCount++;
                    lastReturned = null;
                    Hashtable.this.modCount++;
                    Hashtable.this.count--;
                    return;
                }
            }
            throw new ConcurrentModificationException();
        }
    }
}

Hashtable构造函数:

/**
 * 使用指定的初始容量和默认负载因子(0.75)构造新的空哈希表
 *
 * @param     initialCapacity   the initial capacity of the hashtable.
 * @exception IllegalArgumentException if the initial capacity is less
 *              than zero.
 */
public Hashtable(int initialCapacity) {
    this(initialCapacity, 0.75f);
}

/**
 * 使用默认的初始容量(11)和默认负载因子(0.75)构造新的空哈希表
 */
public Hashtable() {
    this(11, 0.75f);
}

/**
 * 使用与给定映射相同的映射和默认的负载因子(0.75)构造新的哈希表
 * Hashtable的初始容量足以容纳给定映射中的映射
 *
 * @param t the map whose mappings are to be placed in this map.
 * @throws NullPointerException if the specified map is null.
 * @since   1.2
 */
public Hashtable(Map<? extends K, ? extends V> t) {
    this(Math.max(2*t.size(), 11), 0.75f);
    putAll(t);
}

/**
 * 来自Properties的构造函数保持Hashtable字段未初始化
 *
 * @param dummy a dummy parameter
 */
Hashtable(Void dummy) {}

Hashtable的其他方法:


/**
 * 返回此散列表中键的枚举, 使用返回对象上的枚举方法按顺序获取键
 *
 * @return  an enumeration of the keys in this hashtable.
 * @see     Enumeration
 * @see     #elements()
 * @see     #keySet()
 * @see     Map
 */
public synchronized Enumeration<K> keys() {
    return this.<K>getEnumeration(KEYS);
}

/**
 * 返回此散列表中值的枚举, 使用返回对象的枚举方法按顺序获取元素
 *
 * @return  an enumeration of the values in this hashtable.
 * @see     java.util.Enumeration
 * @see     #keys()
 * @see     #values()
 * @see     Map
 */
public synchronized Enumeration<V> elements() {
    return this.<V>getEnumeration(VALUES);
}

/**
 * 测试某些键是否映射到此散列表中的指定值
 * 这个操作比containsKey方法更昂贵
 *
 * 此方法在功能上与containsValue相同
 *
 * @param      value   a value to search for
 * @return     {@code true} if and only if some key maps to the
 *             {@code value} argument in this hashtable as
 *             determined by the {@code equals} method;
 *             {@code false} otherwise.
 * @exception  NullPointerException  if the value is {@code null}
 */
public synchronized boolean contains(Object value) {
    if (value == null) {
        throw new NullPointerException();
    }

    Entry<?,?> tab[] = table;
    for (int i = tab.length ; i-- > 0 ;) {
        for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
            if (e.value.equals(value)) {
                return true;
            }
        }
    }
    return false;
}

/**
 * 测试指定的对象是否是此散列表中的键
 *
 * @param   key   possible key
 * @return  {@code true} if and only if the specified object
 *          is a key in this hashtable, as determined by the
 *          {@code equals} method; {@code false} otherwise.
 * @throws  NullPointerException  if the key is {@code null}
 * @see     #contains(Object)
 */
public synchronized boolean containsKey(Object key) {
    Entry<?,?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
        if ((e.hash == hash) && e.key.equals(key)) {
            return true;
        }
    }
    return false;
}

/**
 * 返回指定键映射到的值, 如果此映射不包含键的映射, 则返回null
 * 满足key.equals(k), 则返回e.value
 *
 * @param key the key whose associated value is to be returned
 * @return the value to which the specified key is mapped, or
 *         {@code null} if this map contains no mapping for the key
 * @throws NullPointerException if the specified key is null
 * @see     #put(Object, Object)
 */
@SuppressWarnings("unchecked")
public synchronized V get(Object key) {
    Entry<?,?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
        if ((e.hash == hash) && e.key.equals(key)) {
            return (V)e.value;
        }
    }
    return null;
}

/**
 * 增加此散列表的容量并在内部重新组织此散列表
 * 当哈希表中的键数超过此哈希表的容量和负载因子时, 自动调用此方法
 */
@SuppressWarnings("unchecked")
protected void rehash() {
    int oldCapacity = table.length;
    Entry<?,?>[] oldMap = table;

    // overflow-conscious code
    int newCapacity = (oldCapacity << 1) + 1; // oldCapacity * 2 + 1
    if (newCapacity - MAX_ARRAY_SIZE > 0) {
        if (oldCapacity == MAX_ARRAY_SIZE)
            // Keep running with MAX_ARRAY_SIZE buckets
            return;
        // 扩容超过最大值则设定为最大值
        newCapacity = MAX_ARRAY_SIZE;
    }
    Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];

    modCount++;
    // 阈值 = min(新容量 * 负载因子, hashtable最大容量)
    threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
    table = newMap;

    // 插入元素
    for (int i = oldCapacity ; i-- > 0 ;) {
        for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
            Entry<K,V> e = old;
            old = old.next;

            int index = (e.hash & 0x7FFFFFFF) % newCapacity;
            e.next = (Entry<K,V>)newMap[index];
            newMap[index] = e;
        }
    }
}

private void addEntry(int hash, K key, V value, int index) {
    Entry<?,?> tab[] = table;
    if (count >= threshold) { // 当前 > 阈值
        // 扩容哈希表
        rehash();

        tab = table;
        hash = key.hashCode();
        index = (hash & 0x7FFFFFFF) % tab.length;
    }

    // Creates the new entry.
    @SuppressWarnings("unchecked")
    Entry<K,V> e = (Entry<K,V>) tab[index];
    tab[index] = new Entry<>(hash, key, value, e);  // 插入条目
    count++;
    modCount++;
}

/**
 * 将指定的键映射到此散列表中指定的值
 * key 和 value 都不能为null
 *
 * @param      key     the hashtable key
 * @param      value   the value
 * @return     the previous value of the specified key in this hashtable,
 *             or {@code null} if it did not have one
 * @exception  NullPointerException  if the key or value is
 *               {@code null}
 * @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();
    }

    // Makes sure the key is not already in the hashtable.
    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;    //若key已存在则更新值, 然后返回旧值
            return old;
        }
    }

    addEntry(hash, key, value, index);  // 若无则新建一条条目
    return null;
}

/**
 * 从这个哈希表中删除键(及其对应的值)
 *
 * @param   key   the key that needs to be removed
 * @return  the value to which the key had been mapped in this hashtable,
 *          or {@code null} if the key did not have a mapping
 * @throws  NullPointerException  if the key is {@code null}
 */
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];
    for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {
        if ((e.hash == hash) && e.key.equals(key)) {
            if (prev != null) {
                prev.next = e.next;
            } else {
                tab[index] = e.next;
            }
            modCount++;
            count--;
            V oldValue = e.value;
            e.value = null;
            return oldValue;
        }
    }
    return null;
}

/**
 * 根据映射接口中的定义返回此映射的散列代码值
 *
 * @see Map#hashCode()
 * @since 1.2
 */
public synchronized int hashCode() {
    /*
        * This code detects the recursion caused by computing the hash code
        * of a self-referential hash table and prevents the stack overflow
        * that would otherwise result.  This allows certain 1.1-era
        * applets with self-referential hash tables to work.  This code
        * abuses the loadFactor field to do double-duty as a hashCode
        * in progress flag, so as not to worsen the space performance.
        * A negative load factor indicates that hash code computation is
        * in progress.
        */
    int h = 0;
    if (count == 0 || loadFactor < 0)
        return h;  // Returns zero

    loadFactor = -loadFactor;  // Mark hashCode computation in progress
    Entry<?,?>[] tab = table;
    for (Entry<?,?> entry : tab) {
        while (entry != null) {
            h += entry.hashCode();
            entry = entry.next;
        }
    }

    loadFactor = -loadFactor;  // Mark hashCode computation complete

    return h;
}

 Hashtable总结

Hashtable基于数组和链表实现的存储结构

Hashtable是线程安全的,使用synchronized关键字

Hashtable性能比HashMap低,且不允许插入null元素

Hashtable的初始容量=11,负载因子=0.75

Hashtable每次扩容,新容量=旧容量 * 2 + 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值