Hashtable 源码解析

Hashtable 底层是以数组加链表实现的,是线程安全。

 

    private transient Entry<?,?>[] table;//全局变量,存放hashtable的数据

  private float loadFactor;//全局变量,负载因子

   public Hashtable() {//空参数的构造函数
        this(11, 0.75f); //调用带参构造函数,默认初始化数组长度为11,负载因子0.75
    }

 

// 带初始化数

 public Hashtable(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)//当初始化长度、和负载因子小于0史抛出异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal Load: "+loadFactor);

        if (initialCapacity==0)=
            initialCapacity = 1;//当初始化数组长度为0时设为1
        this.loadFactor = loadFactor;//装载因子赋值给全局变量
        table = new Entry<?,?>[initialCapacity];//初始化一个长度为initialCapacity的数组
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);//阈值=初始化容量*负载因子
    }

 

 public synchronized V put(K key, V value) {// 往hashtable中放key 和value
        // Make sure the value is not null
        if (value == null) {// value 不能为空,否则抛出空指针异常
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry<?,?> tab[] = table; //把table的值赋值给tab[]  数组
        int hash = key.hashCode();//获取key值得hashCode
        int index = (hash & 0x7FFFFFFF) % tab.length;   //获取hash表的index值
        @SuppressWarnings("unchecked")
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        for(; entry != null ; entry = entry.next) { // 判断key是否存在,存在覆盖原来的值
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);//  往hashtable中添加新的元素
        return null;
    }

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(); //对hashtable 重新扩容

            tab = table;//重新对tab赋值
            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++;
    }

 

//对hashtable进行扩容

@SuppressWarnings("unchecked")
    protected void rehash() {
        int oldCapacity = table.length;//原来数组长度
        Entry<?,?>[] oldMap = table;

        // overflow-conscious code
        int newCapacity = (oldCapacity << 1) + 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];//创建新的hashtable

        modCount++;
        threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);// 修改阈值
        table = newMap;//把新创建的数组赋值给table

       //把旧的hashtable在扩容后重新排列

       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;// 把当前元素赋值给计算出index下标的数组
            }
        }
    }

 @SuppressWarnings("unchecked")
    public synchronized V get(Object key) {  
        Entry<?,?> tab[] = table;//把table 的全局变量赋值给tab
        int hash = key.hashCode();//获取key对应的hashcode
        int index = (hash & 0x7FFFFFFF) % tab.length;//求余获取对应数组下标
        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {//循环数组下标对应的链表,找到key值一样的元素返回
            if ((e.hash == hash) && e.key.equals(key)) {
                return (V)e.value;
            }
        }
        return null;
    }
 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值