Hashtable学习笔记

Hashtable常用特点区分:    
1、extends Dictionary ;
2、线程安全;
3、key和value!=null;
4、默认容量11;负载因子0.75;
5、容量扩展old<<2+1.
 
 /**
*源码浅析
*/
//继承Dictionary实现Map, Cloneable, java.io.Serializable
public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable
 
 
 
//4个构造,同HashMap一样
 
 
//第一个构造传入容量和负载因子
public Hashtable(int initialCapacity, float loadFactor) {
        //传入容量不能小于0,
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        //负载因子不能小于等于0或者是非数
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal Load: "+loadFactor);
         //如果容量为0,则置为1,容量最小就是1
        if (initialCapacity==0)
            initialCapacity = 1;
        this.loadFactor = loadFactor;
          //table是以容量大小为初始大小的数组
        table = new Entry[initialCapacity];
         //临界值计算=容量乘以负载因子和当前系统数组最大长度加1的最小值,当达到临界值就需要扩容
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        initHashSeedAsNeeded(initialCapacity);
    }
 
// 添加初始的容量,负载因子默认0.75
public Hashtable(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }
// 容器默认11,负载因子默认0.75
public Hashtable() {
        this(11, 0.75f);
    }
// 初始容器取map最大尺寸*2和11取大的,也就是最小也是11,负载因子0.75
public Hashtable(Map<? extends K, ? extends V> t) {
        this(Math.max(2*t.size(), 11), 0.75f);
          //调用putAll将map中的数据加入hashtable中
        putAll(t);
    }
 
//Hashtable大部分方法属性都是加了同步锁,所以Hashtable是线程安全的
 
//返回所有key枚举对象
public synchronized Enumeration<K> keys() {
        return this.<K>getEnumeration(KEYS);
    }
 
//返回所有value枚举对象
public synchronized Enumeration<V> elements() {
        return this.<V>getEnumeration(VALUES);
    }
 
//判断Hashtable的值是否等于value
public synchronized boolean contains(Object value) {
        //value不能等于null
        if (value == null) {
            throw new NullPointerException();
        }
        //遍历数组查找数组元素是否与value相等
        Entry tab[] = table;
        for (int i = tab.length ; i-- > 0 ;) {
            for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {
                if (e.value.equals(value)) {
                    return true;
                }
            }
        }
        return false;
    }
 
//判断Hashtable是否包含传入key
public synchronized boolean containsKey(Object key) {
        Entry tab[] = table;
        //获取key的hash值
        int hash = hash(key);
        //计算在数组的索引
        int index = (hash & 0x7FFFFFFF) % tab.length;
        //找到key对应的链表,找出hash值和key值都相等的元素
        for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return true;
            }
        }
        return false;
    }
 
 
 //返回key对应的value,没有值得话返回null
 public synchronized V get(Object key) {
        Entry tab[] = table;
        //计算key对应的hash值
        int hash = hash(key);
        //根据hash计算对应的索引
        int index = (hash & 0x7FFFFFFF) % tab.length;
        //根据索引找到对应的链表,在链表中查找hash值和key值都相等的元素
        for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return e.value;
            }
        }
        return null;
    }
 
 
//调整Hashtable的长度,使其达到(oldCapacity << 1) + 1
protected void rehash() {
        int oldCapacity = table.length;
        Entry<K,V>[] 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<K,V>[] newMap = new Entry[newCapacity];
 
        modCount++;
        //临界值=新容量*负载因子和数组元素实际容量加1的min
        threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        boolean rehash = initHashSeedAsNeeded(newCapacity);
 
        table = newMap;
        //将原有元素复制到新的Hashtable中
        for (int i = oldCapacity ; i-- > 0 ;) {
            for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
                Entry<K,V> e = old;
                old = old.next;
 
                if (rehash) {
                    e.hash = hash(e.key);
                }
                //计算新索引
                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                e.next = newMap[index];
                newMap[index] = e;
            }
        }
    }
 
 
//添加键值对
public synchronized V put(K key, V value) {
        // value不等于null
        if (value == null) {
            throw new NullPointerException();
        }
 
        //若添加的key在Hashtable已经存在,则用新value覆盖原有的value
        Entry tab[] = table;
        int hash = hash(key);
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                V old = e.value;
                e.value = value;
                return old;
            }
        }
        //若不存在键值等于key的键值对,+1
        modCount++;
        //如果Hashtable实际容量大于临界值,扩容
        if (count >= threshold) {
            // Rehash the table if the threshold is exceeded
            rehash();
 
            tab = table;
            hash = hash(key);
            index = (hash & 0x7FFFFFFF) % tab.length;
        }
 
        // Creates the new entry.
        //将新的键值对插入对应数组索引为index的位置所在链表的表头.
        Entry<K,V> e = tab[index];
        tab[index] = new Entry<>(hash, key, value, e);
        count++;
        return null;
    }
 
 
//删除键值为key的键值对
public synchronized V remove(Object key) {
        Entry tab[] = table;
        int hash = hash(key);
        //计算索引
        int index = (hash & 0x7FFFFFFF) % tab.length;
        //因为是单链表,所以删除的时候要保留要删除节点的前一个节点
        for (Entry<K,V> e = tab[index], 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;
    }
 
//多次调用put方法添加数据
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());
}
 
//通过遍历数组的方式将数组元素key值置为null,value不理会
public synchronized void clear() {
        Entry tab[] = table;
        modCount++;
        for (int index = tab.length; --index >= 0; )
            tab[index] = null;
        count = 0;
    }
 
//克隆Hashtable
public synchronized Object clone() {
        try {
            //克隆一个相同的空Hashtable
            Hashtable<K,V> t = (Hashtable<K,V>) super.clone();
            t.table = new Entry[table.length];
            //将原有元素一次克隆到相应位置
            for (int i = table.length ; i-- > 0 ; ) {
                t.table[i] = (table[i] != null)
                    ? (Entry<K,V>) 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();
        }
    }
 
//重写toString,遍历元素,生成{"key" = "value"},当长度达到最大值,结束
public synchronized String toString() {
        int max = size() - 1;
        if (max == -1)
            return "{}";
 
        StringBuilder sb = new StringBuilder();
        Iterator<Map.Entry<K,V>> it = entrySet().iterator();
 
        sb.append('{');
        for (int i = 0; ; i++) {
            Map.Entry<K,V> e = it.next();
            K key = e.getKey();
            V value = e.getValue();
            sb.append(key   == this ? "(this Map)" : key.toString());
            sb.append('=');
            sb.append(value == this ? "(this Map)" : value.toString());
 
            if (i == max)
                return sb.append('}').toString();
            sb.append(", ");
        }
    }
 
 
 
 
posted @ 2017-09-11 10:06  麻辣香蕉  阅读(157)  评论(0编辑  收藏  举报