Java--集合--Hashtable

  1. Hashtable基本介绍 
  2. Hashtable 源码解析
    1.  执行 new Hashtable()
      1. public Hashtable() {
                this(11, 0.75f);
            }
        //默认的调用有参构造函数,且数组成都为11,加载因子为0.75
      2. 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;
        //创建一个长度为11的Entry类型的table数组
                table = new Entry<?,?>[initialCapacity];  
        //获取临界值 threshold
        = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1); }
    2.  执行put方法

      1.   

         public synchronized V put(K key, V value) {
                // Make sure the value is not null
        //如果value==null抛出空指针异常
        if (value == null) { throw new NullPointerException(); } // Makes sure the key is not already in the hashtable.
        //创建一个tab数组指向,table Entry<?,?> tab[] = table;
        //计算出key的hash值
        int hash = key.hashCode();
        //key计算出的索引
        int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked")
        //拿到tab数组中下标为 index的节点entry Entry
        <K,V> entry = (Entry<K,V>)tab[index];
        //循环遍历,下标为index的链表中是否存在和 要插入的元素一样的,如果有就将原来的value进行替换
        for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } //如果遍历完了整个链表都没有和key相等的元素,就调用addentry()方法,将他加入到链表中 addEntry(hash, key, value, index); return null; }

         

         
      2. private void addEntry(int hash, K key, V value, int index) {
                modCount++; //操作数加一
        //创建的tab数组
                Entry<?,?> tab[] = table;
        //判断如果节点数超过临界值就进行 rehash()方法进行扩容,操作,因为操作数的增加时在末尾,所以第八的元素添加时不会进行扩容,之后第九个元素进来的时候才会进行扩容操作
        if (count >= threshold) {
                    // Rehash the table if the threshold is exceeded
                    rehash();
        
                    tab = table;
                    hash = key.hashCode();
                    index = (hash & 0x7FFFFFFF) % tab.length;
                }
        //没有超过临界值,就将元素加入到 tab[index]上
                // Creates the new entry.
                @SuppressWarnings("unchecked")
                Entry<K,V> e = (Entry<K,V>) tab[index];
                tab[index] = new Entry<>(hash, key, value, e);
                count++;
            }

         

      3.  protected void rehash() {
        //得到旧表的长度
        int oldCapacity = table.length;
        //新建一个表指向旧表 Entry
        <?,?>[] oldMap = table; // overflow-conscious code
        //信表长度等于旧表长度*2+1
        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; }
        //新建一个长度为 newCapacity的新表 Entry
        <?,?>[] newMap = new Entry<?,?>[newCapacity]; //被修改的次数 modCount++;
        //新的临界值 threshold
        = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        //将表table执行新建的表 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; } } }

         

  3. 源码底说明

    1.  底层数组Hashtable$Entry[]初始化大小是11

    2. 临界值时 0.75,临界值时0.75*11=8 

    3. 扩容机制:大于八的时候就会发生扩容,扩容为原来的一倍在加1:
       int newCapacity = (oldCapacity << 1) + 1;
  4. Hashtable和HashMap的对比

    1.  

       

       

        

        
posted @ 2021-06-15 18:38  张紫韩  阅读(38)  评论(0编辑  收藏  举报