Java源代码之Hashtable

Java源代码之Hashtable




转载请注明出处:http://blog.csdn.net/itismelzp/article/details/50553711


一、Hashtable概述

类实现一个哈希表。该哈希表将键key对象映射到对应的值value对象。要求key和value都非null。为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。

Hashtable是线程同步的,可是非线程同步的HashMap全然能够代替它。

假设不须要线程安全,能够直接使用HashMap代替;

假设须要线程安全高并发,能够使用java.util.concurrent.ConcurrentHashMap代替。


二、Hashtable数据结构

Hashtable与jdk1.8之前的HashMap一样,是用数组+链表实现。

/**
 * Hashtable数组冲突链结点
 */
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(); } }



三、Hashtable源代码


1.头文件

package java.util;

import java.io.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.BiFunction;



2.实现与继承

public class Hashtable<K,V>
	extends Dictionary<K,V>
	implements Map<K,V>, Cloneable, java.io.Serializable



3.属性

/**
 * hash表数组
 */
private transient Entry<?,?>[] table;

/**
 * 数组中存储的元素个数
 */
private transient int count;

/**
 * 阈值。超过这个值数组要扩容
 * threshold = capacity * loadFactor
 */
private int threshold;

/**
 * 装载因子
 */
private float loadFactor;

/**
 * 改动次数
 * 採用fail-fast机制
 */
private transient int modCount = 0;


4.构造器与方法

这部分与HashMap的主要差别是,hash函数的算法。

这里用的是典型的除留取余法:

int index = (hash & 0x7FFFFFFF) % tab.length;


这部分的构造器、方法与HashMap的区别不大,仅仅是在方法前面加了synchronized使方法同步。


/**
 * 构造方法一:
 * 用指定容量 + 指定装载因子构造
 */
public Hashtable(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal Load: "+loadFactor);

    if (initialCapacity==0)
        initialCapacity = 1;
    this.loadFactor = loadFactor;
    table = new Entry<?,?>[initialCapacity];
    threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
}

/**
 * 构造方法二:
 * 指定容量 + 默认装载因子构造
 */
public Hashtable(int initialCapacity) {
    this(initialCapacity, 0.75f);
}

/**
 * 构造方法三:
 * 使用默认容量11 + 默认装载因子
 */
public Hashtable() {
    this(11, 0.75f);
}

/**
 * 构造方法四:
 * 使用Map构造
 */
public Hashtable(Map<? extends K, ?

extends V> t) { this(Math.max(2*t.size(), 11), 0.75f); putAll(t); } /** * 返回容量大小 */ public synchronized int size() { return count; } /** * 判空 */ public synchronized boolean isEmpty() { return count == 0; } /** * 返回全部key值的枚举集合 */ public synchronized Enumeration<K> keys() { return this.<K>getEnumeration(KEYS); } /** * 返回全部value值的枚举集合 */ public synchronized Enumeration<V> elements() { return this.<V>getEnumeration(VALUES); } /** * 推断是否包括value值对象 */ 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; } /** * 推断是否包括value值对象 */ public boolean containsValue(Object value) { return contains(value); } /** * 推断是否包括key键值对象 */ 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; } /** * 获取键值key相应的value */ @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; } /** * 规定的最大数组容量 */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * 扩容(2*oldCap + 1) */ @SuppressWarnings("unchecked") protected void rehash() { int oldCapacity = table.length; Entry<?,?>[] oldMap = table; // overflow-conscious code int newCapacity = (oldCapacity << 1) + 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++; 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) { modCount++; Entry<?,?> tab[] = table; if (count >= threshold) { // Rehash the table if the threshold is exceeded 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++; } /** * 加入元素 * 原key键值存在。返回原key键相应的value * 原key键值不存在。返回null */ 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; return old; } } addEntry(hash, key, value, index); return null; } /** * 删除并返回要删除的value */ 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)) { 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; } /** * 将Map中的元素加入进来 */ public synchronized void putAll(Map<? extends K, ? extends V> t) { for (Map.Entry<? extends K, ?

extends V> e : t.entrySet()) put(e.getKey(), e.getValue()); } /** * 清空 */ public synchronized void clear() { Entry<?

,?> tab[] = table; modCount++; for (int index = tab.length; --index >= 0; ) tab[index] = null; count = 0; } /** * 克隆对象 */ public synchronized Object clone() { try { Hashtable<?

,?

> t = (Hashtable<?,?

>)super.clone(); t.table = new Entry<?

,?>[table.length]; for (int i = table.length ; i-- > 0 ; ) { t.table[i] = (table[i] != null) ?

(Entry<?

,?>) table[i].clone() : null; } t.keySet = null; t.entrySet = null; t.values = null; t.modCount = 0; return t; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(e); } } private <T> Enumeration<T> getEnumeration(int type) { if (count == 0) { return Collections.emptyEnumeration(); } else { return new Enumerator<>(type, false); } } // 获得迭代器 private <T> Iterator<T> getIterator(int type) { if (count == 0) { return Collections.emptyIterator(); } else { return new Enumerator<>(type, true); } } // Views /** * Each of these fields are initialized to contain an instance of the * appropriate view the first time this view is requested. The views are * stateless, so there's no reason to create more than one of each. */ private transient volatile Set<K> keySet; private transient volatile Set<Map.Entry<K,V>> entrySet; private transient volatile Collection<V> values; /** * 返回包括此map的Set视图 * 通过Set视图可获得迭代器Iterator对象,对map进行迭代 */ public Set<Map.Entry<K,V>> entrySet() { if (entrySet==null) entrySet = Collections.synchronizedSet(new EntrySet(), this); return entrySet; } // Set视图类 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)) { modCount++; if (prev != null) prev.next = e.next; else tab[index] = e.next; count--; e.value = null; return true; } } return false; } public int size() { return count; } public void clear() { Hashtable.this.clear(); } } /** * Returns a {@link Collection} view of the values contained in this map. * The collection is backed by the map, so changes to the map are * reflected in the collection, and vice-versa. If the map is * modified while an iteration over the collection is in progress * (except through the iterator's own <tt>remove</tt> operation), * the results of the iteration are undefined. The collection * supports element removal, which removes the corresponding * mapping from the map, via the <tt>Iterator.remove</tt>, * <tt>Collection.remove</tt>, <tt>removeAll</tt>, * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not * support the <tt>add</tt> or <tt>addAll</tt> operations. * * @since 1.2 */ public Collection<V> values() { if (values==null) values = Collections.synchronizedCollection(new ValueCollection(), this); return values; } private class ValueCollection extends AbstractCollection<V> { public Iterator<V> iterator() { return getIterator(VALUES); } public int size() { return count; } public boolean contains(Object o) { return containsValue(o); } public void clear() { Hashtable.this.clear(); } } // Comparison and hashing /** * 实现equals * 判等 */ public synchronized boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Map)) return false; Map<?,?> t = (Map<?,?>) o; if (t.size() != size()) return false; try { Iterator<Map.Entry<K,V>> i = entrySet().iterator(); while (i.hasNext()) { Map.Entry<K,V> e = i.next(); K key = e.getKey(); V value = e.getValue(); if (value == null) { if (!(t.get(key)==null && t.containsKey(key))) return false; } else { if (!value.equals(t.get(key))) return false; } } } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; } return true; } /** * 实现hashCode */ 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; } @Override public synchronized boolean replace(K key, V oldValue, V newValue) { Objects.requireNonNull(oldValue); Objects.requireNonNull(newValue); 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 (; e != null; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { if (e.value.equals(oldValue)) { e.value = newValue; return true; } else { return false; } } } return false; } /* * 替换 */ @Override public synchronized V replace(K key, V value) { Objects.requireNonNull(value); 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 (; e != null; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { V oldValue = e.value; e.value = value; return oldValue; } } return null; }




原文地址:https://www.cnblogs.com/wgwyanfs/p/7128139.html