Java集合汇总源码分解:Hashtable源码分解
当前位置:以往代写 > JAVA 教程 >Java集合汇总源码分解:Hashtable源码分解
2019-06-14

Java集合汇总源码分解:Hashtable源码分解

Java集合汇总源码分解:Hashtable源码分解

副标题#e#

Hashtable简介

Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表办理斗嘴问题,容量不敷(高出了阀值)时,同样会自动增长。

Hashtable也是JDK1.0引入的类,是线程安详的,能用于多线程情况中。

Hashtable同样实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆。

HashTable源码分解

Hashtable的源码的许多实现都与HashMap差不多,源码如下(插手了较量具体的注释):

package java.util;    
import java.io.*;    
       
public class Hashtableextends Dictionaryimplements Map, Cloneable, java.io.Serializable {    
       
    // 生存key-value的数组。    
    // Hashtable同样回收单链表办理斗嘴,每一个Entry本质上是一个单向链表    
    private transient Entry[] table;    
       
    // Hashtable中键值对的数量    
    private transient int count;    
       
    // 阈值,用于判定是否需要调解Hashtable的容量(threshold = 容量*加载因子)    
    private int threshold;    
       
    // 加载因子    
    private float loadFactor;    
       
    // Hashtable被改变的次数,用于fail-fast机制的实现    
    private transient int modCount = 0;    
       
    // 序列版本号    
    private static final long serialVersionUID = 1421746759512286392L;    
       
    // 指定“容量巨细”和“加载因子”的结构函数    
    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)(initialCapacity * loadFactor);    
    }    
       
    // 指定“容量巨细”的结构函数    
    public Hashtable(int initialCapacity) {    
        this(initialCapacity, 0.75f);    
    }    
       
    // 默认结构函数。    
    public Hashtable() {    
        // 默认结构函数,指定的容量巨细是11;加载因子是0.75    
        this(11, 0.75f);    
    }    
       
    // 包括“子Map”的结构函数    
    public Hashtable(Map t) {    
        this(Math.max(2*t.size(), 11), 0.75f);    
        // 将“子Map”的全部元素都添加到Hashtable中    
        putAll(t);    
    }    
       
    public synchronized int size() {    
        return count;    
    }    
       
    public synchronized boolean isEmpty() {    
        return count == 0;    
    }    
       
    // 返回“所有key”的列举工具    
    public synchronized Enumerationkeys() {    
        return this.getEnumeration(KEYS);    
    }    
       
    // 返回“所有value”的列举工具    
    public synchronized Enumerationelements() {    
        return this.getEnumeration(VALUES);    
    }    
       
    // 判定Hashtable是否包括“值(value)”    
    public synchronized boolean contains(Object value) {    
        //留意,Hashtable中的value不能是null,    
        // 若是null的话,抛出异常!    
        if (value == null) {    
            throw new NullPointerException();    
        }    
       
        // 从后向前遍历table数组中的元素(Entry)    
        // 对付每个Entry(单向链表),逐个遍历,判定节点的值是否便是value    
        Entry tab[] = table;    
        for (int i = tab.length ; i-- > 0 ;) {    
            for (Entrye = tab[i] ; e != null ; e = e.next) {    
                if (e.value.equals(value)) {    
                    return true;    
                }    
            }    
        }    
        return false;    
    }    
       
    public boolean containsValue(Object value) {    
        return contains(value);    
    }    
       
    // 判定Hashtable是否包括key    
    public synchronized boolean containsKey(Object key) {    
        Entry tab[] = table;    
        //计较hash值,直接用key的hashCode取代  
        int hash = key.hashCode();      
        // 计较在数组中的索引值   

        int index = (hash & 0x7FFFFFFF) % tab.length;    
        // 找到“key对应的Entry(链表)”,然后在链表中找出“哈希值”和“键值”与key都相等的元素    
        for (Entrye = 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;    
        int hash = key.hashCode();    
        // 计较索引值,    
        int index = (hash & 0x7FFFFFFF) % tab.length;    
        // 找到“key对应的Entry(链表)”,然后在链表中找出“哈希值”和“键值”与key都相等的元素    
        for (Entrye = tab[index] ; e != null ; e = e.next) {    
            if ((e.hash == hash) && e.key.equals(key)) {    
                return e.value;    
            }    
        }    
        return null;    
    }    
       
    // 调解Hashtable的长度,将长度酿本钱来的2倍+1   
    protected void rehash() {    
        int oldCapacity = table.length;    
        Entry[] oldMap = table;    
       
        //建设新容量巨细的Entry数组  
        int newCapacity = oldCapacity * 2 + 1;    
        Entry[] newMap = new Entry[newCapacity];    
       
        modCount++;    
        threshold = (int)(newCapacity * loadFactor);    
        table = newMap;    
              
        //将“旧的Hashtable”中的元素复制到“新的Hashtable”中  
        for (int i = oldCapacity ; i-- > 0 ;) {    
            for (Entryold = oldMap[i] ; old != null ; ) {    
                Entrye = old;    
                old = old.next;    
                //从头计较index  
                int index = (e.hash & 0x7FFFFFFF) % newCapacity;    
                e.next = newMap[index];    
                newMap[index] = e;    
            }    
        }    
    }    
       
    // 将“key-value”添加到Hashtable中    
    public synchronized V put(K key, V value) {    
        // Hashtable中不能插入value为null的元素!!!    
        if (value == null) {    
            throw new NullPointerException();    
        }    
       
        // 若“Hashtable中已存在键为key的键值对”,    
        // 则用“新的value”替换“旧的value”    
        Entry tab[] = table;    
        int hash = key.hashCode();    
        int index = (hash & 0x7FFFFFFF) % tab.length;    
        for (Entrye = tab[index] ; e != null ; e = e.next) {    
            if ((e.hash == hash) && e.key.equals(key)) {    
                V old = e.value;    
                e.value = value;    
                return old;    
                }    
        }    
       
        // 若“Hashtable中不存在键为key的键值对”,  
        // 将“修改统计数”+1    
        modCount++;    
        //  若“Hashtable实际容量” > “阈值”(阈值=总的容量 * 加载因子)    
        //  则调解Hashtable的巨细    
        if (count >= threshold) {  
            rehash();    
       
            tab = table;    
            index = (hash & 0x7FFFFFFF) % tab.length;    
        }    
       
        //将新的key-value对插入到tab[index]处(即链表的头结点)  
        Entrye = tab[index];           
        tab[index] = new Entry(hash, key, value, e);    
        count++;    
        return null;    
    }    
       
    // 删除Hashtable中键为key的元素    
    public synchronized V remove(Object key) {    
        Entry tab[] = table;    
        int hash = key.hashCode();    
        int index = (hash & 0x7FFFFFFF) % tab.length;    
              
        //从table[index]链表中找出要删除的节点,并删除该节点。  
        //因为是单链表,因此要保存带删节点的前一个节点,才气有效地删除节点  
        for (Entrye = 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;    
    }    
       
    // 将“Map(t)”的中全部元素逐一添加到Hashtable中    
    public synchronized void putAll(Map t) {    
        for (Map.Entry e : t.entrySet())    
            put(e.getKey(), e.getValue());    
    }    
       
    // 清空Hashtable    
    // 将Hashtable的table数组的值全部设为null 
// 本栏目
		#p#副标题#e#1、二者的存储布局息争决战嘴的要领都是沟通的。#p#分页标题#e#2、HashTable在不指定容量的环境下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量必然要为2的整数次幂,而HashMap则要求必然为2的整数次幂。#p#分页标题#e#3、Hashtable中key和value都不答允为null,而HashMap中key和value都答允为null(key只能有一个为null,而value则可以有多个为null)。可是假如在Hashtable中有雷同put(null,null)的操纵,编译同样可以通过,因为key和value都是Object范例,但运行时会抛出NullPointerException异常,这是JDK的类型划定的。我们来看下ContainsKey要领和ContainsValue的源码:// 判定Hashtable是否包括“值(value)”    
 public synchronized boolean contains(Object value) {    
     //留意,Hashtable中的value不能是null,
	 // 本栏目4、Hashtable扩容时,将容量变为本来的2倍加1,而HashMap扩容时,将容量变为本来的2倍。5、Hashtable计较hash值,直接用key的hashCode(),而HashMap从头计较了key的hash值,Hashtable在求hash值对应的位置索引时,用取模运算,而HashMap在求位置索引时,则用与运算,且这里一般先用hash&0x7FFFFFFF后,再对length取模,&0x7FFFFFFF的目标是为了将负的hash值转化为正值,因为hash值有大概为负数,而&0x7FFFFFFF后,只有标记外改变,尔后头的位都稳定。

    关键字:

在线提交作业